mirror of
https://github.com/zkemail/zk-regex.git
synced 2026-01-08 21:27:56 -05:00
Integrate vrm in halo2-regex/tests in email-wallet
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -106,3 +106,7 @@ dist
|
||||
.vscode
|
||||
build/*
|
||||
!build/.placeholder
|
||||
|
||||
target
|
||||
|
||||
index.node
|
||||
1464
Cargo.lock
generated
Normal file
1464
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[workspace]
|
||||
members = ["packages/*"]
|
||||
exclude = ["packages/circom", "test"]
|
||||
|
||||
# [patch."https://github.com/stalwartlabs/mail-builder"]
|
||||
# mail-builder = { version = "0.2.5", git = "https://github.com/stalwartlabs//mail-builder", tag = "0.2.5" }
|
||||
|
||||
# [patch."https://github.com/stalwartlabs/mail-parser"]
|
||||
# mail-parser = { version = "0.8", git = "https://github.com/stalwartlabs//mail-parser", tag = "0.8.0" }
|
||||
11
babel.config.js
Normal file
11
babel.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
['@babel/preset-env', { targets: { node: 'current' } }],
|
||||
'@babel/preset-typescript',
|
||||
['@babel/preset-react', { "runtime": "automatic" }],
|
||||
['jest']
|
||||
],
|
||||
plugins: [
|
||||
'@babel/plugin-transform-modules-commonjs',
|
||||
]
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
pragma circom 2.0.3;
|
||||
|
||||
include "../node_modules/circomlib/circuits/comparators.circom";
|
||||
include "../node_modules/circomlib/circuits/gates.circom";
|
||||
|
||||
template MultiOROld(n) {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
component or1;
|
||||
component or2;
|
||||
component ors[2];
|
||||
if (n==1) {
|
||||
out <== in[0];
|
||||
} else if (n==2) {
|
||||
or1 = OR();
|
||||
or1.a <== in[0];
|
||||
or1.b <== in[1];
|
||||
out <== or1.out;
|
||||
} else {
|
||||
or2 = OR();
|
||||
var n1 = n\2;
|
||||
var n2 = n-n\2;
|
||||
ors[0] = MultiOR(n1);
|
||||
ors[1] = MultiOR(n2);
|
||||
var i;
|
||||
for (i=0; i<n1; i++) ors[0].in[i] <== in[i];
|
||||
for (i=0; i<n2; i++) ors[1].in[i] <== in[n1+i];
|
||||
or2.a <== ors[0].out;
|
||||
or2.b <== ors[1].out;
|
||||
out <== or2.out;
|
||||
}
|
||||
}
|
||||
|
||||
template MultiOR(n) {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
|
||||
signal sums[n];
|
||||
sums[0] <== in[0];
|
||||
for (var i = 1; i < n; i++) {
|
||||
sums[i] <== sums[i-1] + in[i];
|
||||
}
|
||||
|
||||
component is_zero = IsZero();
|
||||
is_zero.in <== sums[n-1];
|
||||
out <== 1 - is_zero.out;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
const generator = require('../compiler/gen');
|
||||
|
||||
const program = require('commander');
|
||||
const unescapeJs = require('unescape-js');
|
||||
|
||||
program.version('0.0.1')
|
||||
.description('A sample CLI program');
|
||||
|
||||
program.command('compile <regex> <circuit_name>')
|
||||
.description('Compile a regular expression into circom circuits')
|
||||
.action((regex, circuit_name) => {
|
||||
regex = unescapeJs(regex);
|
||||
generator.generateCircuit(regex, undefined, circuit_name);
|
||||
});
|
||||
|
||||
program.on('command:*', () => {
|
||||
console.error(
|
||||
'Error: Invalid command. See --help for a list of available commands.'
|
||||
);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
if (!process.args.length) {
|
||||
program.help();
|
||||
}
|
||||
258
compiler/gen.js
258
compiler/gen.js
@@ -1,258 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const regexpTree = require('regexp-tree');
|
||||
const assert = require('assert');
|
||||
const lexical = require('./lexical');
|
||||
|
||||
async function generateCircuit(regex, circuitLibPath, circuitName) {
|
||||
const ast = regexpTree.parse(`/${regex}/`);
|
||||
regexpTree.traverse(ast, {
|
||||
'*': function ({ node }) {
|
||||
if (node.type === 'CharacterClass') {
|
||||
throw new Error('CharacterClass not supported');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const graph_json = lexical.compile(regex);
|
||||
const N = graph_json.length;
|
||||
|
||||
// Outgoing nodes
|
||||
const graph = Array.from({ length: N }, () => ({}));
|
||||
// Incoming Nodes
|
||||
const rev_graph = Array.from({ length: N }, () => []);
|
||||
const accept_nodes = new Set();
|
||||
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let k in graph_json[i]['edges']) {
|
||||
//assert len(k) == 1
|
||||
//assert ord(k) < 128
|
||||
const v = graph_json[i]['edges'][k];
|
||||
graph[i][k] = v;
|
||||
rev_graph[v].push([k, i]);
|
||||
}
|
||||
if (graph_json[i]['type'] === 'accept') {
|
||||
accept_nodes.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
assert.strictEqual(accept_nodes.size, 1);
|
||||
|
||||
let eq_i = 0;
|
||||
let lt_i = 0;
|
||||
let and_i = 0;
|
||||
let multi_or_i = 0;
|
||||
|
||||
let lines = [];
|
||||
lines.push('for (var i = 0; i < num_bytes; i++) {');
|
||||
|
||||
assert.strictEqual(accept_nodes.has(0), false);
|
||||
|
||||
for (let i = 1; i < N; i++) {
|
||||
const outputs = [];
|
||||
for (let [k, prev_i] of rev_graph[i]) {
|
||||
let vals = new Set(JSON.parse(k));
|
||||
const eq_outputs = [];
|
||||
|
||||
const uppercase = new Set('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''));
|
||||
const lowercase = new Set('abcdefghijklmnopqrstuvwxyz'.split(''));
|
||||
const digits = new Set('0123456789'.split(''));
|
||||
|
||||
if (new Set([...uppercase].filter((x) => vals.has(x))).size === uppercase.size) {
|
||||
vals = new Set([...vals].filter((x) => !uppercase.has(x)));
|
||||
lines.push('\t//UPPERCASE');
|
||||
lines.push(`\tlt[${lt_i}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[0] <== 64;`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== in[i];`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
lines.push(`\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\tand[${and_i}][i].a <== lt[${lt_i}][i].out;`);
|
||||
lines.push(`\tand[${and_i}][i].b <== lt[${lt_i + 1}][i].out;`);
|
||||
|
||||
eq_outputs.push(['and', and_i]);
|
||||
lt_i += 2;
|
||||
and_i += 1;
|
||||
}
|
||||
if (new Set([...lowercase].filter((x) => vals.has(x))).size === lowercase.size) {
|
||||
vals = new Set([...vals].filter((x) => !lowercase.has(x)));
|
||||
lines.push('\t//lowercase');
|
||||
lines.push(`\tlt[${lt_i}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[0] <== 96;`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== in[i];`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
lines.push(`\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\tand[${and_i}][i].a <== lt[${lt_i}][i].out;`);
|
||||
lines.push(`\tand[${and_i}][i].b <== lt[${lt_i + 1}][i].out;`);
|
||||
|
||||
eq_outputs.push(['and', and_i]);
|
||||
lt_i += 2;
|
||||
and_i += 1;
|
||||
}
|
||||
if (new Set([...digits].filter((x) => vals.has(x))).size === digits.size) {
|
||||
vals = new Set([...vals].filter((x) => !digits.has(x)));
|
||||
lines.push('\t//digits');
|
||||
lines.push(`\tlt[${lt_i}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[0] <== 47;`);
|
||||
lines.push(`\tlt[${lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== in[i];`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
lines.push(`\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\tand[${and_i}][i].a <== lt[${lt_i}][i].out;`);
|
||||
lines.push(`\tand[${and_i}][i].b <== lt[${lt_i + 1}][i].out;`);
|
||||
|
||||
eq_outputs.push(['and', and_i]);
|
||||
lt_i += 2;
|
||||
and_i += 1;
|
||||
}
|
||||
for (let c of vals) {
|
||||
assert.strictEqual(c.length, 1);
|
||||
lines.push(`\t//${c}`);
|
||||
lines.push(`\teq[${eq_i}][i] = IsEqual();`);
|
||||
lines.push(`\teq[${eq_i}][i].in[0] <== in[i];`);
|
||||
lines.push(`\teq[${eq_i}][i].in[1] <== ${c.charCodeAt(0)};`);
|
||||
eq_outputs.push(['eq', eq_i]);
|
||||
eq_i += 1;
|
||||
}
|
||||
|
||||
lines.push(`\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\tand[${and_i}][i].a <== states[i][${prev_i}];`);
|
||||
|
||||
if (eq_outputs.length === 1) {
|
||||
lines.push(`\tand[${and_i}][i].b <== ${eq_outputs[0][0]}[${eq_outputs[0][1]}][i].out;`);
|
||||
} else if (eq_outputs.length > 1) {
|
||||
lines.push(`\tmulti_or[${multi_or_i}][i] = MultiOR(${eq_outputs.length});`);
|
||||
for (let output_i = 0; output_i < eq_outputs.length; output_i++) {
|
||||
lines.push(`\tmulti_or[${multi_or_i}][i].in[${output_i}] <== ${eq_outputs[output_i][0]}[${eq_outputs[output_i][1]}][i].out;`);
|
||||
}
|
||||
lines.push(`\tand[${and_i}][i].b <== multi_or[${multi_or_i}][i].out;`);
|
||||
multi_or_i += 1;
|
||||
}
|
||||
outputs.push(and_i);
|
||||
and_i += 1;
|
||||
}
|
||||
|
||||
if (outputs.length === 1) {
|
||||
lines.push(`\tstates[i+1][${i}] <== and[${outputs[0]}][i].out;`);
|
||||
} else if (outputs.length > 1) {
|
||||
lines.push(`\tmulti_or[${multi_or_i}][i] = MultiOR(${outputs.length});`);
|
||||
for (let output_i = 0; output_i < outputs.length; output_i++) {
|
||||
lines.push(`\tmulti_or[${multi_or_i}][i].in[${output_i}] <== and[${outputs[output_i]}][i].out;`);
|
||||
}
|
||||
lines.push(`\tstates[i+1][${i}] <== multi_or[${multi_or_i}][i].out;`);
|
||||
multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lines.push('}');
|
||||
|
||||
lines.push('signal final_state_sum[num_bytes+1];');
|
||||
lines.push(`final_state_sum[0] <== states[0][${N - 1}];`);
|
||||
lines.push('for (var i = 1; i <= num_bytes; i++) {');
|
||||
lines.push(`\tfinal_state_sum[i] <== final_state_sum[i-1] + states[i][${N - 1}];`);
|
||||
lines.push('}');
|
||||
lines.push('entire_count <== final_state_sum[num_bytes];');
|
||||
|
||||
let declarations = [];
|
||||
|
||||
if (eq_i > 0) {
|
||||
declarations.push(`component eq[${eq_i}][num_bytes];`);
|
||||
}
|
||||
if (lt_i > 0) {
|
||||
declarations.push(`component lt[${lt_i}][num_bytes];`);
|
||||
}
|
||||
if (and_i > 0) {
|
||||
declarations.push(`component and[${and_i}][num_bytes];`);
|
||||
}
|
||||
if (multi_or_i > 0) {
|
||||
declarations.push(`component multi_or[${multi_or_i}][num_bytes];`);
|
||||
}
|
||||
declarations.push(`signal states[num_bytes+1][${N}];`);
|
||||
declarations.push('');
|
||||
|
||||
let init_code = [];
|
||||
|
||||
init_code.push('for (var i = 0; i < num_bytes; i++) {');
|
||||
init_code.push('\tstates[i][0] <== 1;');
|
||||
init_code.push('}');
|
||||
|
||||
init_code.push(`for (var i = 1; i < ${N}; i++) {`);
|
||||
init_code.push('\tstates[0][i] <== 0;');
|
||||
init_code.push('}');
|
||||
|
||||
init_code.push('');
|
||||
|
||||
// construct the match group indexes
|
||||
const node_edges = graph_json.map((node) =>
|
||||
Object.keys(node.edges).map((key) => {
|
||||
return { [key]: node.edges[key] };
|
||||
})
|
||||
);
|
||||
const node_edges_flat = node_edges.flat();
|
||||
|
||||
const node_edges_set = new Set();
|
||||
node_edges_flat.forEach((node) => {
|
||||
if (JSON.parse(Object.keys(node)[0]).length > 1) {
|
||||
node_edges_set.add(Object.values(node)[0]);
|
||||
}
|
||||
});
|
||||
const match_group_indexes = Array.from(node_edges_set).sort((a, b) => a - b);
|
||||
init_code.push(`var match_group_indexes[${match_group_indexes.length}] = [${match_group_indexes.join(', ')}];`);
|
||||
|
||||
const reveal_code = [];
|
||||
reveal_code.push('signal output reveal[num_bytes];');
|
||||
reveal_code.push('for (var i = 0; i < num_bytes; i++) {');
|
||||
reveal_code.push('\treveal[i] <== in[i] * states[i+1][match_group_indexes[group_idx]];');
|
||||
reveal_code.push('}');
|
||||
reveal_code.push('');
|
||||
|
||||
lines = [...declarations, ...init_code, ...lines, ...reveal_code];
|
||||
|
||||
const OUTPUT_HALO2 = true;
|
||||
if (OUTPUT_HALO2) {
|
||||
console.log('Logging to halo2 file! Note that this file is not formatted correctly. For the latest spec, see https://github.com/zkemail/halo2-regex');
|
||||
const f = fs.createWriteStream('halo2_regex_lookup_js.txt');
|
||||
accept_nodes.forEach((a) => f.write(a + ' '));
|
||||
f.write('\n');
|
||||
f.write(match_group_indexes.join(' '));
|
||||
f.write('\n');
|
||||
for (let i = 0; i < N; i++) {
|
||||
const edges = graph_json[i]['edges'];
|
||||
for (let k in edges) {
|
||||
const v = edges[k];
|
||||
for (let val of JSON.parse(k)) {
|
||||
f.write(`${i} ${v} ${val.charCodeAt(0)}\n`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
let tpl = await (await fs.promises.readFile(`${__dirname}/tpl.circom`)).toString();
|
||||
tpl = tpl.replace('TEMPLATE_NAME_PLACEHOLDER', circuitName || 'Regex');
|
||||
tpl = tpl.replace('COMPILED_CONTENT_PLACEHOLDER', lines.join('\n\t'));
|
||||
tpl = tpl.replace(/CIRCUIT_FOLDER/g, circuitLibPath || '../circuits');
|
||||
tpl = tpl.replace(/\t/g, ' '.repeat(4));
|
||||
|
||||
const outputPath = `${__dirname}/../build/${circuitName || 'compiled'}.circom`;
|
||||
await fs.promises.writeFile(outputPath, tpl);
|
||||
process.env.VERBOSE && console.log(`Circuit compiled to ${path.normalize(outputPath)}`);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
generateCircuit,
|
||||
...lexical,
|
||||
};
|
||||
@@ -1,83 +0,0 @@
|
||||
pragma circom 2.0.3;
|
||||
|
||||
include "CIRCUIT_FOLDER/regex_helpers.circom";
|
||||
|
||||
template TEMPLATE_NAME_PLACEHOLDER (msg_bytes, reveal_bytes, group_idx) {
|
||||
signal input msg[msg_bytes];
|
||||
signal input match_idx;
|
||||
signal output start_idx;
|
||||
signal output group_match_count;
|
||||
signal output entire_count;
|
||||
|
||||
signal reveal_shifted_intermediate[reveal_bytes][msg_bytes];
|
||||
signal output reveal_shifted[reveal_bytes];
|
||||
|
||||
var num_bytes = msg_bytes;
|
||||
signal in[num_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i] <== msg[i];
|
||||
}
|
||||
|
||||
COMPILED_CONTENT_PLACEHOLDER
|
||||
|
||||
// a flag to indicate the start position of the match
|
||||
var start_index = 0;
|
||||
// for counting the number of matches
|
||||
var count = 0;
|
||||
|
||||
// lengths to be consistent with states signal
|
||||
component check_start[num_bytes + 1];
|
||||
component check_match[num_bytes + 1];
|
||||
component check_matched_start[num_bytes + 1];
|
||||
component matched_idx_eq[msg_bytes];
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
if (i == 0) {
|
||||
count += states[1][match_group_indexes[group_idx]];
|
||||
}
|
||||
else {
|
||||
check_start[i] = AND();
|
||||
check_start[i].a <== states[i + 1][match_group_indexes[group_idx]];
|
||||
check_start[i].b <== 1 - states[i][match_group_indexes[group_idx]];
|
||||
|
||||
count += check_start[i].out;
|
||||
|
||||
check_match[i] = IsEqual();
|
||||
check_match[i].in[0] <== count;
|
||||
check_match[i].in[1] <== match_idx + 1;
|
||||
|
||||
check_matched_start[i] = AND();
|
||||
check_matched_start[i].a <== check_match[i].out;
|
||||
check_matched_start[i].b <== check_start[i].out;
|
||||
start_index += check_matched_start[i].out * i;
|
||||
}
|
||||
|
||||
matched_idx_eq[i] = IsEqual();
|
||||
matched_idx_eq[i].in[0] <== states[i + 1][match_group_indexes[group_idx]] * count;
|
||||
matched_idx_eq[i].in[1] <== match_idx + 1;
|
||||
}
|
||||
|
||||
component match_start_idx[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
match_start_idx[i] = IsEqual();
|
||||
match_start_idx[i].in[0] <== i;
|
||||
match_start_idx[i].in[1] <== start_index;
|
||||
}
|
||||
|
||||
signal reveal_match[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
reveal_match[i] <== matched_idx_eq[i].out * reveal[i];
|
||||
}
|
||||
|
||||
for (var j = 0; j < reveal_bytes; j++) {
|
||||
reveal_shifted_intermediate[j][j] <== 0;
|
||||
for (var i = j + 1; i < msg_bytes; i++) {
|
||||
// This shifts matched string back to the beginning.
|
||||
reveal_shifted_intermediate[j][i] <== reveal_shifted_intermediate[j][i - 1] + match_start_idx[i-j].out * reveal_match[i];
|
||||
}
|
||||
reveal_shifted[j] <== reveal_shifted_intermediate[j][msg_bytes - 1];
|
||||
}
|
||||
|
||||
group_match_count <== count;
|
||||
start_idx <== start_index;
|
||||
}
|
||||
42
package.json
42
package.json
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "zk-regex",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "zk regex circuit for content attestation",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"main": "node-apis/index.node",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "NODE_OPTIONS=--max_old_space_size=56000 mocha --timeout 600000 'test/**/*.js'",
|
||||
"lint": "eslint ./",
|
||||
"compile": "VERBOSE=1 node compiler/cli.js compile"
|
||||
"test": "yarn workspaces -pt run test",
|
||||
"lint": "eslint ./"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -28,21 +28,19 @@
|
||||
"url": "https://github.com/zk-email-verify/zk-regex/issues"
|
||||
},
|
||||
"homepage": "https://github.com/zk-email-verify/zk-regex#readme",
|
||||
"dependencies": {
|
||||
"circomlib": "^2.0.2",
|
||||
"commander": "^10.0.0",
|
||||
"eslint": "^8.34.0",
|
||||
"regexp-tree": "^0.1.24",
|
||||
"unescape-js": "^1.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.3.0",
|
||||
"@types/expect": "^24.3.0",
|
||||
"@types/mocha": "^9.0.0",
|
||||
"chai": "^4.3.4",
|
||||
"circom_tester": "katat/circom_tester#feat/signal-json",
|
||||
"mocha": "^9.1.3",
|
||||
"ts-node": "^10.4.0",
|
||||
"@babel/core": "^7.22.5",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.22.15",
|
||||
"@babel/preset-env": "^7.22.2",
|
||||
"@babel/preset-react": "^7.22.0",
|
||||
"@babel/preset-typescript": "^7.21.5",
|
||||
"@types/jest": "^29.5.4",
|
||||
"babel-jest": "^29.5.0",
|
||||
"babel-preset-jest": "^29.5.0",
|
||||
"jest": "^29.5.0",
|
||||
"prettier": "^3.0.0",
|
||||
"prettier-plugin-solidity": "^1.1.3",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^4.5.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
packages/apis/.gitignore
vendored
Normal file
5
packages/apis/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
target
|
||||
index.node
|
||||
**/node_modules
|
||||
**/.DS_Store
|
||||
npm-debug.log*
|
||||
24
packages/apis/Cargo.toml
Normal file
24
packages/apis/Cargo.toml
Normal file
@@ -0,0 +1,24 @@
|
||||
[package]
|
||||
name = "zk-regex-apis"
|
||||
version = "0.1.0"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
exclude = ["index.node"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
compiler = { package = "zk-regex-compiler", path = "../compiler", default-features = false }
|
||||
fancy-regex = "0.11.0"
|
||||
itertools = "0.10.3"
|
||||
thiserror = "1.0.40"
|
||||
serde_json = "1.0.95"
|
||||
|
||||
|
||||
[dependencies.neon]
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
features = ["napi-6"]
|
||||
119
packages/apis/README.md
Normal file
119
packages/apis/README.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# zk-regex-apis
|
||||
|
||||
This project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
|
||||
|
||||
## Installing zk-regex-apis
|
||||
|
||||
Installing zk-regex-apis requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).
|
||||
|
||||
You can install the project with npm. In the project directory, run:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
```
|
||||
|
||||
This fully installs the project, including installing any dependencies and running the build.
|
||||
|
||||
## Building zk-regex-apis
|
||||
|
||||
If you have already installed the project and only want to run the build, run:
|
||||
|
||||
```sh
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
This command uses the [cargo-cp-artifact](https://github.com/neon-bindings/cargo-cp-artifact) utility to run the Rust build and copy the built library into `./index.node`.
|
||||
|
||||
## Exploring zk-regex-apis
|
||||
|
||||
After building zk-regex-apis, you can explore its exports at the Node REPL:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
$ node
|
||||
> require('.').hello()
|
||||
"hello node"
|
||||
```
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm install`
|
||||
|
||||
Installs the project, including running `npm run build`.
|
||||
|
||||
### `npm build`
|
||||
|
||||
Builds the Node addon (`index.node`) from source.
|
||||
|
||||
Additional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm build` and `npm build-*` commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):
|
||||
|
||||
```
|
||||
npm run build -- --feature=beetle
|
||||
```
|
||||
|
||||
#### `npm build-debug`
|
||||
|
||||
Alias for `npm build`.
|
||||
|
||||
#### `npm build-release`
|
||||
|
||||
Same as [`npm build`](#npm-build) but, builds the module with the [`release`](https://doc.rust-lang.org/cargo/reference/profiles.html#release) profile. Release builds will compile slower, but run faster.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Runs the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).
|
||||
|
||||
## Project Layout
|
||||
|
||||
The directory structure of this project is:
|
||||
|
||||
```
|
||||
zk-regex-apis/
|
||||
├── Cargo.toml
|
||||
├── README.md
|
||||
├── index.node
|
||||
├── package.json
|
||||
├── src/
|
||||
| └── lib.rs
|
||||
└── target/
|
||||
```
|
||||
|
||||
### Cargo.toml
|
||||
|
||||
The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.
|
||||
|
||||
### README.md
|
||||
|
||||
This file.
|
||||
|
||||
### index.node
|
||||
|
||||
The Node addon—i.e., a binary Node module—generated by building the project. This is the main module for this package, as dictated by the `"main"` key in `package.json`.
|
||||
|
||||
Under the hood, a [Node addon](https://nodejs.org/api/addons.html) is a [dynamically-linked shared object](https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries). The `"build"` script produces this file by copying it from within the `target/` directory, which is where the Rust build produces the shared object.
|
||||
|
||||
### package.json
|
||||
|
||||
The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.
|
||||
|
||||
### src/
|
||||
|
||||
The directory tree containing the Rust source code for the project.
|
||||
|
||||
### src/lib.rs
|
||||
|
||||
The Rust library's main module.
|
||||
|
||||
### target/
|
||||
|
||||
Binary artifacts generated by the Rust build.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Neon, see the [Neon documentation](https://neon-bindings.com).
|
||||
|
||||
To learn more about Rust, see the [Rust documentation](https://www.rust-lang.org).
|
||||
|
||||
To learn more about Node, see the [Node documentation](https://nodejs.org).
|
||||
18
packages/apis/package.json
Normal file
18
packages/apis/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "zk-regex-apis",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.node",
|
||||
"scripts": {
|
||||
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
|
||||
"build-debug": "npm run build --",
|
||||
"build-release": "npm run build -- --release",
|
||||
"install": "npm run build-release",
|
||||
"test": "cargo test"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"cargo-cp-artifact": "^0.1"
|
||||
}
|
||||
}
|
||||
216
packages/apis/src/extract_substrs.rs
Normal file
216
packages/apis/src/extract_substrs.rs
Normal file
@@ -0,0 +1,216 @@
|
||||
use fancy_regex::Regex;
|
||||
use compiler::{DecomposedRegexConfig};
|
||||
use itertools::Itertools;
|
||||
use neon::prelude::*;
|
||||
use thiserror::Error;
|
||||
use serde_json;
|
||||
|
||||
/// Error definitions of the compiler.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ExtractSubstrssError {
|
||||
#[error("The max length is {} but the input length is {}",.0,.1)]
|
||||
InvalidInputLen(usize, usize),
|
||||
#[error("Substring of the entire regex {} is not found in {}",.0,.1)]
|
||||
SubstringOfEntireNotFound(Regex,String),
|
||||
#[error("Substring of {} is not found in {}",.0,.1)]
|
||||
SubstringNotFound(Regex,String),
|
||||
#[error(transparent)]
|
||||
RegexError(#[from] fancy_regex::Error),
|
||||
}
|
||||
|
||||
|
||||
pub fn extract_substr_idxes(
|
||||
input_str: &str,
|
||||
regex_config: &DecomposedRegexConfig,
|
||||
) -> Result<Vec<(usize,usize)>,ExtractSubstrssError> {
|
||||
if input_str.len() > regex_config.max_byte_size {
|
||||
return Err(ExtractSubstrssError::InvalidInputLen(regex_config.max_byte_size,input_str.len()));
|
||||
}
|
||||
let mut entire_regex_str = String::new();
|
||||
for part in regex_config.parts.iter() {
|
||||
entire_regex_str += part.regex_def.as_str();
|
||||
}
|
||||
// entire_regex_str = format_regex_printable(&entire_regex_str)?;
|
||||
let entire_regex = Regex::new(&entire_regex_str)?;
|
||||
let entire_found = entire_regex.find(input_str)?.ok_or_else(|| {
|
||||
ExtractSubstrssError::SubstringOfEntireNotFound(entire_regex, input_str.to_string())
|
||||
})?;
|
||||
let mut start = entire_found.start();
|
||||
let entire_end = entire_found.end();
|
||||
|
||||
let mut public_idxes = vec![];
|
||||
// let mut last_regex_str = String::new();
|
||||
// let part_regex_defs = regex_config.parts.iter().map(|part| part.regex_def.as_str()).collect_vec();
|
||||
for part_idx in 0..regex_config.parts.len() {
|
||||
// last_regex_str = last_regex_str + regex_config.parts[part_idx].regex_def.as_str();
|
||||
let regex = Regex::new(®ex_config.parts[part_idx].regex_def.as_str())?;
|
||||
let found = regex.find_from_pos(&input_str,start)?.ok_or_else(|| {
|
||||
ExtractSubstrssError::SubstringNotFound(regex.clone(), input_str[start..entire_end].to_string())
|
||||
})?;
|
||||
let end = found.end();
|
||||
// if found.start() >= end {
|
||||
// return Err(ExtractSubstrssError::EmptySubstring(regex, input_str[start..entire_end].to_string()));
|
||||
// }
|
||||
if regex_config.parts[part_idx].is_public {
|
||||
public_idxes.push((start,end));
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
|
||||
Ok(public_idxes)
|
||||
}
|
||||
|
||||
pub fn extract_substr_idxes_node(
|
||||
mut cx: FunctionContext
|
||||
) -> JsResult<JsArray> {
|
||||
let input_str = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let regex_config_str = cx.argument::<JsString>(1)?.value(&mut cx);
|
||||
let regex_config = match serde_json::from_str::<DecomposedRegexConfig>(®ex_config_str){
|
||||
Ok(regex_config) => regex_config,
|
||||
Err(e) => return cx.throw_error(e.to_string())
|
||||
};
|
||||
let substr_idxes = match extract_substr_idxes(&input_str, ®ex_config){
|
||||
Ok(substr_idxes) => substr_idxes,
|
||||
Err(e) => return cx.throw_error(e.to_string())
|
||||
};
|
||||
let js_array = JsArray::new(&mut cx, substr_idxes.len() as u32);
|
||||
for (i, (start_idx,end_idx)) in substr_idxes.iter().enumerate() {
|
||||
let start_end_array = JsArray::new(&mut cx,2u32);
|
||||
let start_idx = cx.number(*start_idx as f64);
|
||||
start_end_array.set(&mut cx, 0, start_idx)?;
|
||||
let end_idx = cx.number(*end_idx as f64);
|
||||
start_end_array.set(&mut cx, 1, end_idx)?;
|
||||
js_array.set(&mut cx, i as u32, start_end_array)?;
|
||||
}
|
||||
Ok(js_array)
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use compiler::RegexPartConfig;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_email_domain_valid() {
|
||||
let email_addr_regex = DecomposedRegexConfig {
|
||||
max_byte_size: 256,
|
||||
parts: vec![
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|_|%|\\+|-|=)+".to_string(),
|
||||
max_size: 64,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: "@".to_string(),
|
||||
max_size: 1,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|-)+".to_string(),
|
||||
max_size: 255,
|
||||
solidity: None
|
||||
}
|
||||
]
|
||||
};
|
||||
let input_str = "suegamisora@gmail.com";
|
||||
let idxes = extract_substr_idxes(input_str, &email_addr_regex).unwrap();
|
||||
assert_eq!(idxes, vec![(12,21)]);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_email_addr_in_subject_valid() {
|
||||
let email_addr_regex = DecomposedRegexConfig {
|
||||
max_byte_size: 256,
|
||||
parts: vec![
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|_|%|\\+|-|=)+".to_string(),
|
||||
max_size: 64,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "@".to_string(),
|
||||
max_size: 1,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|-)+".to_string(),
|
||||
max_size: 255,
|
||||
solidity: None
|
||||
}
|
||||
]
|
||||
};
|
||||
let input_str = "This is sent for suegamisora@gmail.com";
|
||||
let idxes = extract_substr_idxes(input_str, &email_addr_regex).unwrap();
|
||||
assert_eq!(idxes, vec![(17, 28),(28,29),(29, 38)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_code_in_subject_valid() {
|
||||
let code_regex = DecomposedRegexConfig {
|
||||
max_byte_size: 1024,
|
||||
parts: vec![
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: "CODE:0x".to_string(),
|
||||
max_size: 7,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)+".to_string(),
|
||||
max_size: 6,
|
||||
solidity: None
|
||||
}
|
||||
]
|
||||
};
|
||||
let input_str = "subject: Email Wallet CODE:0x123abc";
|
||||
let idxes = extract_substr_idxes(input_str, &code_regex).unwrap();
|
||||
assert_eq!(idxes, vec![(29, 35)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_timestamp_valid() {
|
||||
let timestamp_regex = DecomposedRegexConfig {
|
||||
max_byte_size: 1024,
|
||||
parts: vec![
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: "dkim-signature:".to_string(),
|
||||
max_size: 10,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: "((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)+=(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|\"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|\\.|\\/|:|<|=|>|\\?|@|\\[|\\\\|\\]|\\^|_|`|{|\\||}|~| |\t|\n|\r|\\x0b|\\x0c)+; )+t=".to_string(),
|
||||
max_size: 128,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: true,
|
||||
regex_def: "(0|1|2|3|4|5|6|7|8|9)+".to_string(),
|
||||
max_size: 10,
|
||||
solidity: None
|
||||
},
|
||||
RegexPartConfig {
|
||||
is_public: false,
|
||||
regex_def: ";".to_string(),
|
||||
max_size: 1,
|
||||
solidity: None
|
||||
},
|
||||
]
|
||||
};
|
||||
let input_str = "dkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1694989812; x=1695594612; dara=google.com; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=BWETwQ9JDReS4GyR2v2TTR8Bpzj9ayumsWQJ3q7vehs=; b=";
|
||||
let idxes = extract_substr_idxes(input_str, ×tamp_regex).unwrap();
|
||||
assert_eq!(idxes, vec![(80, 90)]);
|
||||
}
|
||||
}
|
||||
12
packages/apis/src/lib.rs
Normal file
12
packages/apis/src/lib.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use neon::prelude::*;
|
||||
pub mod extract_substrs;
|
||||
pub mod padding;
|
||||
use extract_substrs::extract_substr_idxes_node;
|
||||
use padding::pad_string_node;
|
||||
|
||||
#[neon::main]
|
||||
fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
cx.export_function("extractSubstrIdxes", extract_substr_idxes_node)?;
|
||||
cx.export_function("padString", pad_string_node)?;
|
||||
Ok(())
|
||||
}
|
||||
19
packages/apis/src/padding.rs
Normal file
19
packages/apis/src/padding.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use neon::prelude::*;
|
||||
|
||||
pub fn pad_string(str: &str, padded_bytes_size: usize) -> Vec<u8> {
|
||||
let mut padded_bytes = str.as_bytes().to_vec();
|
||||
padded_bytes.append(&mut vec![0; padded_bytes_size - padded_bytes.len()]);
|
||||
padded_bytes
|
||||
}
|
||||
|
||||
pub fn pad_string_node(mut cx: FunctionContext) -> JsResult<JsArray> {
|
||||
let string = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let padded_bytes_size = cx.argument::<JsNumber>(1)?.value(&mut cx) as usize;
|
||||
let padded_bytes = pad_string(&string, padded_bytes_size);
|
||||
let padded_array = JsArray::new(&mut cx, padded_bytes_size as u32);
|
||||
for (idx, byte) in padded_bytes.into_iter().enumerate() {
|
||||
let js_byte = cx.number(byte);
|
||||
padded_array.set(&mut cx, idx as u32, js_byte)?;
|
||||
}
|
||||
Ok(padded_array)
|
||||
}
|
||||
10
packages/circom/circuits/common/email_addr.json
Normal file
10
packages/circom/circuits/common/email_addr.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"max_byte_size": 512,
|
||||
"parts": [
|
||||
{
|
||||
"is_public": true,
|
||||
"regex_def": "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|_|%|\\+|-|=)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|-)+",
|
||||
"max_size": 256
|
||||
}
|
||||
]
|
||||
}
|
||||
276
packages/circom/circuits/common/email_addr_regex.circom
Normal file
276
packages/circom/circuits/common/email_addr_regex.circom
Normal file
@@ -0,0 +1,276 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template EmailAddrRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[17][num_bytes];
|
||||
component lt[24][num_bytes];
|
||||
component and[17][num_bytes];
|
||||
component multi_or[6][num_bytes];
|
||||
signal states[num_bytes+1][4];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 4; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(3);
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 47;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 58;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== lt[0][i].out;
|
||||
and[0][i].b <== lt[1][i].out;
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 64;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 91;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== lt[2][i].out;
|
||||
and[1][i].b <== lt[3][i].out;
|
||||
lt[4][i] = LessThan(8);
|
||||
lt[4][i].in[0] <== 96;
|
||||
lt[4][i].in[1] <== in[i];
|
||||
lt[5][i] = LessThan(8);
|
||||
lt[5][i].in[0] <== in[i];
|
||||
lt[5][i].in[1] <== 123;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== lt[4][i].out;
|
||||
and[2][i].b <== lt[5][i].out;
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 37;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 43;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 45;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 46;
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 61;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 95;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][0];
|
||||
multi_or[0][i] = MultiOR(9);
|
||||
multi_or[0][i].in[0] <== and[0][i].out;
|
||||
multi_or[0][i].in[1] <== and[1][i].out;
|
||||
multi_or[0][i].in[2] <== and[2][i].out;
|
||||
multi_or[0][i].in[3] <== eq[0][i].out;
|
||||
multi_or[0][i].in[4] <== eq[1][i].out;
|
||||
multi_or[0][i].in[5] <== eq[2][i].out;
|
||||
multi_or[0][i].in[6] <== eq[3][i].out;
|
||||
multi_or[0][i].in[7] <== eq[4][i].out;
|
||||
multi_or[0][i].in[8] <== eq[5][i].out;
|
||||
and[3][i].b <== multi_or[0][i].out;
|
||||
lt[6][i] = LessThan(8);
|
||||
lt[6][i].in[0] <== 47;
|
||||
lt[6][i].in[1] <== in[i];
|
||||
lt[7][i] = LessThan(8);
|
||||
lt[7][i].in[0] <== in[i];
|
||||
lt[7][i].in[1] <== 58;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== lt[6][i].out;
|
||||
and[4][i].b <== lt[7][i].out;
|
||||
lt[8][i] = LessThan(8);
|
||||
lt[8][i].in[0] <== 64;
|
||||
lt[8][i].in[1] <== in[i];
|
||||
lt[9][i] = LessThan(8);
|
||||
lt[9][i].in[0] <== in[i];
|
||||
lt[9][i].in[1] <== 91;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== lt[8][i].out;
|
||||
and[5][i].b <== lt[9][i].out;
|
||||
lt[10][i] = LessThan(8);
|
||||
lt[10][i].in[0] <== 96;
|
||||
lt[10][i].in[1] <== in[i];
|
||||
lt[11][i] = LessThan(8);
|
||||
lt[11][i].in[0] <== in[i];
|
||||
lt[11][i].in[1] <== 123;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== lt[10][i].out;
|
||||
and[6][i].b <== lt[11][i].out;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 37;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 43;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 45;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 46;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 61;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 95;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][1];
|
||||
multi_or[1][i] = MultiOR(9);
|
||||
multi_or[1][i].in[0] <== and[4][i].out;
|
||||
multi_or[1][i].in[1] <== and[5][i].out;
|
||||
multi_or[1][i].in[2] <== and[6][i].out;
|
||||
multi_or[1][i].in[3] <== eq[6][i].out;
|
||||
multi_or[1][i].in[4] <== eq[7][i].out;
|
||||
multi_or[1][i].in[5] <== eq[8][i].out;
|
||||
multi_or[1][i].in[6] <== eq[9][i].out;
|
||||
multi_or[1][i].in[7] <== eq[10][i].out;
|
||||
multi_or[1][i].in[8] <== eq[11][i].out;
|
||||
and[7][i].b <== multi_or[1][i].out;
|
||||
multi_or[2][i] = MultiOR(2);
|
||||
multi_or[2][i].in[0] <== and[3][i].out;
|
||||
multi_or[2][i].in[1] <== and[7][i].out;
|
||||
states[i+1][1] <== multi_or[2][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 64;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][1];
|
||||
and[8][i].b <== eq[12][i].out;
|
||||
states[i+1][2] <== and[8][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
lt[12][i] = LessThan(8);
|
||||
lt[12][i].in[0] <== 47;
|
||||
lt[12][i].in[1] <== in[i];
|
||||
lt[13][i] = LessThan(8);
|
||||
lt[13][i].in[0] <== in[i];
|
||||
lt[13][i].in[1] <== 58;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== lt[12][i].out;
|
||||
and[9][i].b <== lt[13][i].out;
|
||||
lt[14][i] = LessThan(8);
|
||||
lt[14][i].in[0] <== 64;
|
||||
lt[14][i].in[1] <== in[i];
|
||||
lt[15][i] = LessThan(8);
|
||||
lt[15][i].in[0] <== in[i];
|
||||
lt[15][i].in[1] <== 91;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== lt[14][i].out;
|
||||
and[10][i].b <== lt[15][i].out;
|
||||
lt[16][i] = LessThan(8);
|
||||
lt[16][i].in[0] <== 96;
|
||||
lt[16][i].in[1] <== in[i];
|
||||
lt[17][i] = LessThan(8);
|
||||
lt[17][i].in[0] <== in[i];
|
||||
lt[17][i].in[1] <== 123;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== lt[16][i].out;
|
||||
and[11][i].b <== lt[17][i].out;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 45;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 46;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== states[i][2];
|
||||
multi_or[3][i] = MultiOR(5);
|
||||
multi_or[3][i].in[0] <== and[9][i].out;
|
||||
multi_or[3][i].in[1] <== and[10][i].out;
|
||||
multi_or[3][i].in[2] <== and[11][i].out;
|
||||
multi_or[3][i].in[3] <== eq[13][i].out;
|
||||
multi_or[3][i].in[4] <== eq[14][i].out;
|
||||
and[12][i].b <== multi_or[3][i].out;
|
||||
lt[18][i] = LessThan(8);
|
||||
lt[18][i].in[0] <== 47;
|
||||
lt[18][i].in[1] <== in[i];
|
||||
lt[19][i] = LessThan(8);
|
||||
lt[19][i].in[0] <== in[i];
|
||||
lt[19][i].in[1] <== 58;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== lt[18][i].out;
|
||||
and[13][i].b <== lt[19][i].out;
|
||||
lt[20][i] = LessThan(8);
|
||||
lt[20][i].in[0] <== 64;
|
||||
lt[20][i].in[1] <== in[i];
|
||||
lt[21][i] = LessThan(8);
|
||||
lt[21][i].in[0] <== in[i];
|
||||
lt[21][i].in[1] <== 91;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== lt[20][i].out;
|
||||
and[14][i].b <== lt[21][i].out;
|
||||
lt[22][i] = LessThan(8);
|
||||
lt[22][i].in[0] <== 96;
|
||||
lt[22][i].in[1] <== in[i];
|
||||
lt[23][i] = LessThan(8);
|
||||
lt[23][i].in[0] <== in[i];
|
||||
lt[23][i].in[1] <== 123;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== lt[22][i].out;
|
||||
and[15][i].b <== lt[23][i].out;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 45;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 46;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][3];
|
||||
multi_or[4][i] = MultiOR(5);
|
||||
multi_or[4][i].in[0] <== and[13][i].out;
|
||||
multi_or[4][i].in[1] <== and[14][i].out;
|
||||
multi_or[4][i].in[2] <== and[15][i].out;
|
||||
multi_or[4][i].in[3] <== eq[15][i].out;
|
||||
multi_or[4][i].in[4] <== eq[16][i].out;
|
||||
and[16][i].b <== multi_or[4][i].out;
|
||||
multi_or[5][i] = MultiOR(2);
|
||||
multi_or[5][i].in[0] <== and[12][i].out;
|
||||
multi_or[5][i].in[1] <== and[16][i].out;
|
||||
states[i+1][3] <== multi_or[5][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][3];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][3] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][6];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][1] * states[i+2][2];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][2] * states[i+2][3];
|
||||
is_substr0[i][3] <== is_substr0[i][2] + states[i+1][1] * states[i+2][1];
|
||||
is_substr0[i][4] <== is_substr0[i][3] + states[i+1][0] * states[i+2][1];
|
||||
is_substr0[i][5] <== is_substr0[i][4] + states[i+1][3] * states[i+2][3];
|
||||
is_reveal0[i] <== is_substr0[i][5] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
20
packages/circom/circuits/common/email_domain.json
Normal file
20
packages/circom/circuits/common/email_domain.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"max_byte_size": 256,
|
||||
"parts": [
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|_|%|\\+|-|=)+",
|
||||
"max_size": 64
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "@",
|
||||
"max_size": 1
|
||||
},
|
||||
{
|
||||
"is_public": true,
|
||||
"regex_def": "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\.|-)+",
|
||||
"max_size": 255
|
||||
}
|
||||
]
|
||||
}
|
||||
273
packages/circom/circuits/common/email_domain_regex.circom
Normal file
273
packages/circom/circuits/common/email_domain_regex.circom
Normal file
@@ -0,0 +1,273 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template EmailDomainRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[17][num_bytes];
|
||||
component lt[24][num_bytes];
|
||||
component and[17][num_bytes];
|
||||
component multi_or[6][num_bytes];
|
||||
signal states[num_bytes+1][4];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 4; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(3);
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 47;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 58;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== lt[0][i].out;
|
||||
and[0][i].b <== lt[1][i].out;
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 64;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 91;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== lt[2][i].out;
|
||||
and[1][i].b <== lt[3][i].out;
|
||||
lt[4][i] = LessThan(8);
|
||||
lt[4][i].in[0] <== 96;
|
||||
lt[4][i].in[1] <== in[i];
|
||||
lt[5][i] = LessThan(8);
|
||||
lt[5][i].in[0] <== in[i];
|
||||
lt[5][i].in[1] <== 123;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== lt[4][i].out;
|
||||
and[2][i].b <== lt[5][i].out;
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 37;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 43;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 45;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 46;
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 61;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 95;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][0];
|
||||
multi_or[0][i] = MultiOR(9);
|
||||
multi_or[0][i].in[0] <== and[0][i].out;
|
||||
multi_or[0][i].in[1] <== and[1][i].out;
|
||||
multi_or[0][i].in[2] <== and[2][i].out;
|
||||
multi_or[0][i].in[3] <== eq[0][i].out;
|
||||
multi_or[0][i].in[4] <== eq[1][i].out;
|
||||
multi_or[0][i].in[5] <== eq[2][i].out;
|
||||
multi_or[0][i].in[6] <== eq[3][i].out;
|
||||
multi_or[0][i].in[7] <== eq[4][i].out;
|
||||
multi_or[0][i].in[8] <== eq[5][i].out;
|
||||
and[3][i].b <== multi_or[0][i].out;
|
||||
lt[6][i] = LessThan(8);
|
||||
lt[6][i].in[0] <== 47;
|
||||
lt[6][i].in[1] <== in[i];
|
||||
lt[7][i] = LessThan(8);
|
||||
lt[7][i].in[0] <== in[i];
|
||||
lt[7][i].in[1] <== 58;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== lt[6][i].out;
|
||||
and[4][i].b <== lt[7][i].out;
|
||||
lt[8][i] = LessThan(8);
|
||||
lt[8][i].in[0] <== 64;
|
||||
lt[8][i].in[1] <== in[i];
|
||||
lt[9][i] = LessThan(8);
|
||||
lt[9][i].in[0] <== in[i];
|
||||
lt[9][i].in[1] <== 91;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== lt[8][i].out;
|
||||
and[5][i].b <== lt[9][i].out;
|
||||
lt[10][i] = LessThan(8);
|
||||
lt[10][i].in[0] <== 96;
|
||||
lt[10][i].in[1] <== in[i];
|
||||
lt[11][i] = LessThan(8);
|
||||
lt[11][i].in[0] <== in[i];
|
||||
lt[11][i].in[1] <== 123;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== lt[10][i].out;
|
||||
and[6][i].b <== lt[11][i].out;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 37;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 43;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 45;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 46;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 61;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 95;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][1];
|
||||
multi_or[1][i] = MultiOR(9);
|
||||
multi_or[1][i].in[0] <== and[4][i].out;
|
||||
multi_or[1][i].in[1] <== and[5][i].out;
|
||||
multi_or[1][i].in[2] <== and[6][i].out;
|
||||
multi_or[1][i].in[3] <== eq[6][i].out;
|
||||
multi_or[1][i].in[4] <== eq[7][i].out;
|
||||
multi_or[1][i].in[5] <== eq[8][i].out;
|
||||
multi_or[1][i].in[6] <== eq[9][i].out;
|
||||
multi_or[1][i].in[7] <== eq[10][i].out;
|
||||
multi_or[1][i].in[8] <== eq[11][i].out;
|
||||
and[7][i].b <== multi_or[1][i].out;
|
||||
multi_or[2][i] = MultiOR(2);
|
||||
multi_or[2][i].in[0] <== and[3][i].out;
|
||||
multi_or[2][i].in[1] <== and[7][i].out;
|
||||
states[i+1][1] <== multi_or[2][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 64;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][1];
|
||||
and[8][i].b <== eq[12][i].out;
|
||||
states[i+1][2] <== and[8][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
lt[12][i] = LessThan(8);
|
||||
lt[12][i].in[0] <== 47;
|
||||
lt[12][i].in[1] <== in[i];
|
||||
lt[13][i] = LessThan(8);
|
||||
lt[13][i].in[0] <== in[i];
|
||||
lt[13][i].in[1] <== 58;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== lt[12][i].out;
|
||||
and[9][i].b <== lt[13][i].out;
|
||||
lt[14][i] = LessThan(8);
|
||||
lt[14][i].in[0] <== 64;
|
||||
lt[14][i].in[1] <== in[i];
|
||||
lt[15][i] = LessThan(8);
|
||||
lt[15][i].in[0] <== in[i];
|
||||
lt[15][i].in[1] <== 91;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== lt[14][i].out;
|
||||
and[10][i].b <== lt[15][i].out;
|
||||
lt[16][i] = LessThan(8);
|
||||
lt[16][i].in[0] <== 96;
|
||||
lt[16][i].in[1] <== in[i];
|
||||
lt[17][i] = LessThan(8);
|
||||
lt[17][i].in[0] <== in[i];
|
||||
lt[17][i].in[1] <== 123;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== lt[16][i].out;
|
||||
and[11][i].b <== lt[17][i].out;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 45;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 46;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== states[i][2];
|
||||
multi_or[3][i] = MultiOR(5);
|
||||
multi_or[3][i].in[0] <== and[9][i].out;
|
||||
multi_or[3][i].in[1] <== and[10][i].out;
|
||||
multi_or[3][i].in[2] <== and[11][i].out;
|
||||
multi_or[3][i].in[3] <== eq[13][i].out;
|
||||
multi_or[3][i].in[4] <== eq[14][i].out;
|
||||
and[12][i].b <== multi_or[3][i].out;
|
||||
lt[18][i] = LessThan(8);
|
||||
lt[18][i].in[0] <== 47;
|
||||
lt[18][i].in[1] <== in[i];
|
||||
lt[19][i] = LessThan(8);
|
||||
lt[19][i].in[0] <== in[i];
|
||||
lt[19][i].in[1] <== 58;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== lt[18][i].out;
|
||||
and[13][i].b <== lt[19][i].out;
|
||||
lt[20][i] = LessThan(8);
|
||||
lt[20][i].in[0] <== 64;
|
||||
lt[20][i].in[1] <== in[i];
|
||||
lt[21][i] = LessThan(8);
|
||||
lt[21][i].in[0] <== in[i];
|
||||
lt[21][i].in[1] <== 91;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== lt[20][i].out;
|
||||
and[14][i].b <== lt[21][i].out;
|
||||
lt[22][i] = LessThan(8);
|
||||
lt[22][i].in[0] <== 96;
|
||||
lt[22][i].in[1] <== in[i];
|
||||
lt[23][i] = LessThan(8);
|
||||
lt[23][i].in[0] <== in[i];
|
||||
lt[23][i].in[1] <== 123;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== lt[22][i].out;
|
||||
and[15][i].b <== lt[23][i].out;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 45;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 46;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][3];
|
||||
multi_or[4][i] = MultiOR(5);
|
||||
multi_or[4][i].in[0] <== and[13][i].out;
|
||||
multi_or[4][i].in[1] <== and[14][i].out;
|
||||
multi_or[4][i].in[2] <== and[15][i].out;
|
||||
multi_or[4][i].in[3] <== eq[15][i].out;
|
||||
multi_or[4][i].in[4] <== eq[16][i].out;
|
||||
and[16][i].b <== multi_or[4][i].out;
|
||||
multi_or[5][i] = MultiOR(2);
|
||||
multi_or[5][i].in[0] <== and[12][i].out;
|
||||
multi_or[5][i].in[1] <== and[16][i].out;
|
||||
states[i+1][3] <== multi_or[5][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][3];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][3] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][3];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][2] * states[i+2][3];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][3] * states[i+2][3];
|
||||
is_reveal0[i] <== is_substr0[i][2] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
25
packages/circom/circuits/common/from_addr.json
Normal file
25
packages/circom/circuits/common/from_addr.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"max_byte_size": 1024,
|
||||
"parts": [
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "((\r\n)|^)from:",
|
||||
"max_size": 7
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|\"| |@)+<)?",
|
||||
"max_size": 256
|
||||
},
|
||||
{
|
||||
"is_public": true,
|
||||
"regex_def": "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|\\.|-)+",
|
||||
"max_size": 256
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": ">?\r\n",
|
||||
"max_size": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
759
packages/circom/circuits/common/from_addr_regex.circom
Normal file
759
packages/circom/circuits/common/from_addr_regex.circom
Normal file
@@ -0,0 +1,759 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template FromAddrRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[61][num_bytes];
|
||||
component lt[54][num_bytes];
|
||||
component and[65][num_bytes];
|
||||
component multi_or[23][num_bytes];
|
||||
signal states[num_bytes+1][19];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 19; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(18);
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 47;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 58;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== lt[0][i].out;
|
||||
and[0][i].b <== lt[1][i].out;
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 64;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 91;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== lt[2][i].out;
|
||||
and[1][i].b <== lt[3][i].out;
|
||||
lt[4][i] = LessThan(8);
|
||||
lt[4][i].in[0] <== 96;
|
||||
lt[4][i].in[1] <== in[i];
|
||||
lt[5][i] = LessThan(8);
|
||||
lt[5][i].in[0] <== in[i];
|
||||
lt[5][i].in[1] <== 123;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== lt[4][i].out;
|
||||
and[2][i].b <== lt[5][i].out;
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 46;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 95;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][1];
|
||||
multi_or[0][i] = MultiOR(5);
|
||||
multi_or[0][i].in[0] <== and[0][i].out;
|
||||
multi_or[0][i].in[1] <== and[1][i].out;
|
||||
multi_or[0][i].in[2] <== and[2][i].out;
|
||||
multi_or[0][i].in[3] <== eq[0][i].out;
|
||||
multi_or[0][i].in[4] <== eq[1][i].out;
|
||||
and[3][i].b <== multi_or[0][i].out;
|
||||
lt[6][i] = LessThan(8);
|
||||
lt[6][i].in[0] <== 47;
|
||||
lt[6][i].in[1] <== in[i];
|
||||
lt[7][i] = LessThan(8);
|
||||
lt[7][i].in[0] <== in[i];
|
||||
lt[7][i].in[1] <== 58;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== lt[6][i].out;
|
||||
and[4][i].b <== lt[7][i].out;
|
||||
lt[8][i] = LessThan(8);
|
||||
lt[8][i].in[0] <== 64;
|
||||
lt[8][i].in[1] <== in[i];
|
||||
lt[9][i] = LessThan(8);
|
||||
lt[9][i].in[0] <== in[i];
|
||||
lt[9][i].in[1] <== 91;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== lt[8][i].out;
|
||||
and[5][i].b <== lt[9][i].out;
|
||||
lt[10][i] = LessThan(8);
|
||||
lt[10][i].in[0] <== 96;
|
||||
lt[10][i].in[1] <== in[i];
|
||||
lt[11][i] = LessThan(8);
|
||||
lt[11][i].in[0] <== in[i];
|
||||
lt[11][i].in[1] <== 123;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== lt[10][i].out;
|
||||
and[6][i].b <== lt[11][i].out;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 46;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 95;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][13];
|
||||
multi_or[1][i] = MultiOR(5);
|
||||
multi_or[1][i].in[0] <== and[4][i].out;
|
||||
multi_or[1][i].in[1] <== and[5][i].out;
|
||||
multi_or[1][i].in[2] <== and[6][i].out;
|
||||
multi_or[1][i].in[3] <== eq[2][i].out;
|
||||
multi_or[1][i].in[4] <== eq[3][i].out;
|
||||
and[7][i].b <== multi_or[1][i].out;
|
||||
multi_or[2][i] = MultiOR(2);
|
||||
multi_or[2][i].in[0] <== and[3][i].out;
|
||||
multi_or[2][i].in[1] <== and[7][i].out;
|
||||
states[i+1][1] <== multi_or[2][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 13;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][0];
|
||||
and[8][i].b <== eq[4][i].out;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 13;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== states[i][4];
|
||||
and[9][i].b <== eq[5][i].out;
|
||||
multi_or[3][i] = MultiOR(2);
|
||||
multi_or[3][i].in[0] <== and[8][i].out;
|
||||
multi_or[3][i].in[1] <== and[9][i].out;
|
||||
states[i+1][2] <== multi_or[3][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 32;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 34;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== states[i][1];
|
||||
multi_or[4][i] = MultiOR(2);
|
||||
multi_or[4][i].in[0] <== eq[6][i].out;
|
||||
multi_or[4][i].in[1] <== eq[7][i].out;
|
||||
and[10][i].b <== multi_or[4][i].out;
|
||||
lt[12][i] = LessThan(8);
|
||||
lt[12][i].in[0] <== 47;
|
||||
lt[12][i].in[1] <== in[i];
|
||||
lt[13][i] = LessThan(8);
|
||||
lt[13][i].in[0] <== in[i];
|
||||
lt[13][i].in[1] <== 58;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== lt[12][i].out;
|
||||
and[11][i].b <== lt[13][i].out;
|
||||
lt[14][i] = LessThan(8);
|
||||
lt[14][i].in[0] <== 64;
|
||||
lt[14][i].in[1] <== in[i];
|
||||
lt[15][i] = LessThan(8);
|
||||
lt[15][i].in[0] <== in[i];
|
||||
lt[15][i].in[1] <== 91;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== lt[14][i].out;
|
||||
and[12][i].b <== lt[15][i].out;
|
||||
lt[16][i] = LessThan(8);
|
||||
lt[16][i].in[0] <== 96;
|
||||
lt[16][i].in[1] <== in[i];
|
||||
lt[17][i] = LessThan(8);
|
||||
lt[17][i].in[0] <== in[i];
|
||||
lt[17][i].in[1] <== 123;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== lt[16][i].out;
|
||||
and[13][i].b <== lt[17][i].out;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 32;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 34;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 46;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 64;
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 95;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== states[i][3];
|
||||
multi_or[5][i] = MultiOR(8);
|
||||
multi_or[5][i].in[0] <== and[11][i].out;
|
||||
multi_or[5][i].in[1] <== and[12][i].out;
|
||||
multi_or[5][i].in[2] <== and[13][i].out;
|
||||
multi_or[5][i].in[3] <== eq[8][i].out;
|
||||
multi_or[5][i].in[4] <== eq[9][i].out;
|
||||
multi_or[5][i].in[5] <== eq[10][i].out;
|
||||
multi_or[5][i].in[6] <== eq[11][i].out;
|
||||
multi_or[5][i].in[7] <== eq[12][i].out;
|
||||
and[14][i].b <== multi_or[5][i].out;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 32;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 34;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 64;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== states[i][12];
|
||||
multi_or[6][i] = MultiOR(3);
|
||||
multi_or[6][i].in[0] <== eq[13][i].out;
|
||||
multi_or[6][i].in[1] <== eq[14][i].out;
|
||||
multi_or[6][i].in[2] <== eq[15][i].out;
|
||||
and[15][i].b <== multi_or[6][i].out;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 32;
|
||||
eq[17][i] = IsEqual();
|
||||
eq[17][i].in[0] <== in[i];
|
||||
eq[17][i].in[1] <== 34;
|
||||
eq[18][i] = IsEqual();
|
||||
eq[18][i].in[0] <== in[i];
|
||||
eq[18][i].in[1] <== 64;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][13];
|
||||
multi_or[7][i] = MultiOR(3);
|
||||
multi_or[7][i].in[0] <== eq[16][i].out;
|
||||
multi_or[7][i].in[1] <== eq[17][i].out;
|
||||
multi_or[7][i].in[2] <== eq[18][i].out;
|
||||
and[16][i].b <== multi_or[7][i].out;
|
||||
eq[19][i] = IsEqual();
|
||||
eq[19][i].in[0] <== in[i];
|
||||
eq[19][i].in[1] <== 32;
|
||||
eq[20][i] = IsEqual();
|
||||
eq[20][i].in[0] <== in[i];
|
||||
eq[20][i].in[1] <== 34;
|
||||
eq[21][i] = IsEqual();
|
||||
eq[21][i].in[0] <== in[i];
|
||||
eq[21][i].in[1] <== 64;
|
||||
and[17][i] = AND();
|
||||
and[17][i].a <== states[i][15];
|
||||
multi_or[8][i] = MultiOR(3);
|
||||
multi_or[8][i].in[0] <== eq[19][i].out;
|
||||
multi_or[8][i].in[1] <== eq[20][i].out;
|
||||
multi_or[8][i].in[2] <== eq[21][i].out;
|
||||
and[17][i].b <== multi_or[8][i].out;
|
||||
multi_or[9][i] = MultiOR(5);
|
||||
multi_or[9][i].in[0] <== and[10][i].out;
|
||||
multi_or[9][i].in[1] <== and[14][i].out;
|
||||
multi_or[9][i].in[2] <== and[15][i].out;
|
||||
multi_or[9][i].in[3] <== and[16][i].out;
|
||||
multi_or[9][i].in[4] <== and[17][i].out;
|
||||
states[i+1][3] <== multi_or[9][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
eq[22][i] = IsEqual();
|
||||
eq[22][i].in[0] <== in[i];
|
||||
eq[22][i].in[1] <== 128;
|
||||
and[18][i] = AND();
|
||||
and[18][i].a <== states[i][0];
|
||||
and[18][i].b <== eq[22][i].out;
|
||||
eq[23][i] = IsEqual();
|
||||
eq[23][i].in[0] <== in[i];
|
||||
eq[23][i].in[1] <== 10;
|
||||
and[19][i] = AND();
|
||||
and[19][i].a <== states[i][2];
|
||||
and[19][i].b <== eq[23][i].out;
|
||||
multi_or[10][i] = MultiOR(2);
|
||||
multi_or[10][i].in[0] <== and[18][i].out;
|
||||
multi_or[10][i].in[1] <== and[19][i].out;
|
||||
states[i+1][4] <== multi_or[10][i].out;
|
||||
state_changed[i].in[3] <== states[i+1][4];
|
||||
eq[24][i] = IsEqual();
|
||||
eq[24][i].in[0] <== in[i];
|
||||
eq[24][i].in[1] <== 60;
|
||||
and[20][i] = AND();
|
||||
and[20][i].a <== states[i][1];
|
||||
and[20][i].b <== eq[24][i].out;
|
||||
eq[25][i] = IsEqual();
|
||||
eq[25][i].in[0] <== in[i];
|
||||
eq[25][i].in[1] <== 60;
|
||||
and[21][i] = AND();
|
||||
and[21][i].a <== states[i][3];
|
||||
and[21][i].b <== eq[25][i].out;
|
||||
eq[26][i] = IsEqual();
|
||||
eq[26][i].in[0] <== in[i];
|
||||
eq[26][i].in[1] <== 60;
|
||||
and[22][i] = AND();
|
||||
and[22][i].a <== states[i][12];
|
||||
and[22][i].b <== eq[26][i].out;
|
||||
eq[27][i] = IsEqual();
|
||||
eq[27][i].in[0] <== in[i];
|
||||
eq[27][i].in[1] <== 60;
|
||||
and[23][i] = AND();
|
||||
and[23][i].a <== states[i][15];
|
||||
and[23][i].b <== eq[27][i].out;
|
||||
multi_or[11][i] = MultiOR(4);
|
||||
multi_or[11][i].in[0] <== and[20][i].out;
|
||||
multi_or[11][i].in[1] <== and[21][i].out;
|
||||
multi_or[11][i].in[2] <== and[22][i].out;
|
||||
multi_or[11][i].in[3] <== and[23][i].out;
|
||||
states[i+1][5] <== multi_or[11][i].out;
|
||||
state_changed[i].in[4] <== states[i+1][5];
|
||||
eq[28][i] = IsEqual();
|
||||
eq[28][i].in[0] <== in[i];
|
||||
eq[28][i].in[1] <== 102;
|
||||
and[24][i] = AND();
|
||||
and[24][i].a <== states[i][4];
|
||||
and[24][i].b <== eq[28][i].out;
|
||||
states[i+1][6] <== and[24][i].out;
|
||||
state_changed[i].in[5] <== states[i+1][6];
|
||||
eq[29][i] = IsEqual();
|
||||
eq[29][i].in[0] <== in[i];
|
||||
eq[29][i].in[1] <== 45;
|
||||
and[25][i] = AND();
|
||||
and[25][i].a <== states[i][1];
|
||||
and[25][i].b <== eq[29][i].out;
|
||||
lt[18][i] = LessThan(8);
|
||||
lt[18][i].in[0] <== 47;
|
||||
lt[18][i].in[1] <== in[i];
|
||||
lt[19][i] = LessThan(8);
|
||||
lt[19][i].in[0] <== in[i];
|
||||
lt[19][i].in[1] <== 58;
|
||||
and[26][i] = AND();
|
||||
and[26][i].a <== lt[18][i].out;
|
||||
and[26][i].b <== lt[19][i].out;
|
||||
lt[20][i] = LessThan(8);
|
||||
lt[20][i].in[0] <== 64;
|
||||
lt[20][i].in[1] <== in[i];
|
||||
lt[21][i] = LessThan(8);
|
||||
lt[21][i].in[0] <== in[i];
|
||||
lt[21][i].in[1] <== 91;
|
||||
and[27][i] = AND();
|
||||
and[27][i].a <== lt[20][i].out;
|
||||
and[27][i].b <== lt[21][i].out;
|
||||
lt[22][i] = LessThan(8);
|
||||
lt[22][i].in[0] <== 96;
|
||||
lt[22][i].in[1] <== in[i];
|
||||
lt[23][i] = LessThan(8);
|
||||
lt[23][i].in[0] <== in[i];
|
||||
lt[23][i].in[1] <== 123;
|
||||
and[28][i] = AND();
|
||||
and[28][i].a <== lt[22][i].out;
|
||||
and[28][i].b <== lt[23][i].out;
|
||||
eq[30][i] = IsEqual();
|
||||
eq[30][i].in[0] <== in[i];
|
||||
eq[30][i].in[1] <== 45;
|
||||
eq[31][i] = IsEqual();
|
||||
eq[31][i].in[0] <== in[i];
|
||||
eq[31][i].in[1] <== 46;
|
||||
eq[32][i] = IsEqual();
|
||||
eq[32][i].in[0] <== in[i];
|
||||
eq[32][i].in[1] <== 95;
|
||||
and[29][i] = AND();
|
||||
and[29][i].a <== states[i][5];
|
||||
multi_or[12][i] = MultiOR(6);
|
||||
multi_or[12][i].in[0] <== and[26][i].out;
|
||||
multi_or[12][i].in[1] <== and[27][i].out;
|
||||
multi_or[12][i].in[2] <== and[28][i].out;
|
||||
multi_or[12][i].in[3] <== eq[30][i].out;
|
||||
multi_or[12][i].in[4] <== eq[31][i].out;
|
||||
multi_or[12][i].in[5] <== eq[32][i].out;
|
||||
and[29][i].b <== multi_or[12][i].out;
|
||||
lt[24][i] = LessThan(8);
|
||||
lt[24][i].in[0] <== 47;
|
||||
lt[24][i].in[1] <== in[i];
|
||||
lt[25][i] = LessThan(8);
|
||||
lt[25][i].in[0] <== in[i];
|
||||
lt[25][i].in[1] <== 58;
|
||||
and[30][i] = AND();
|
||||
and[30][i].a <== lt[24][i].out;
|
||||
and[30][i].b <== lt[25][i].out;
|
||||
lt[26][i] = LessThan(8);
|
||||
lt[26][i].in[0] <== 64;
|
||||
lt[26][i].in[1] <== in[i];
|
||||
lt[27][i] = LessThan(8);
|
||||
lt[27][i].in[0] <== in[i];
|
||||
lt[27][i].in[1] <== 91;
|
||||
and[31][i] = AND();
|
||||
and[31][i].a <== lt[26][i].out;
|
||||
and[31][i].b <== lt[27][i].out;
|
||||
lt[28][i] = LessThan(8);
|
||||
lt[28][i].in[0] <== 96;
|
||||
lt[28][i].in[1] <== in[i];
|
||||
lt[29][i] = LessThan(8);
|
||||
lt[29][i].in[0] <== in[i];
|
||||
lt[29][i].in[1] <== 123;
|
||||
and[32][i] = AND();
|
||||
and[32][i].a <== lt[28][i].out;
|
||||
and[32][i].b <== lt[29][i].out;
|
||||
eq[33][i] = IsEqual();
|
||||
eq[33][i].in[0] <== in[i];
|
||||
eq[33][i].in[1] <== 45;
|
||||
eq[34][i] = IsEqual();
|
||||
eq[34][i].in[0] <== in[i];
|
||||
eq[34][i].in[1] <== 46;
|
||||
eq[35][i] = IsEqual();
|
||||
eq[35][i].in[0] <== in[i];
|
||||
eq[35][i].in[1] <== 95;
|
||||
and[33][i] = AND();
|
||||
and[33][i].a <== states[i][7];
|
||||
multi_or[13][i] = MultiOR(6);
|
||||
multi_or[13][i].in[0] <== and[30][i].out;
|
||||
multi_or[13][i].in[1] <== and[31][i].out;
|
||||
multi_or[13][i].in[2] <== and[32][i].out;
|
||||
multi_or[13][i].in[3] <== eq[33][i].out;
|
||||
multi_or[13][i].in[4] <== eq[34][i].out;
|
||||
multi_or[13][i].in[5] <== eq[35][i].out;
|
||||
and[33][i].b <== multi_or[13][i].out;
|
||||
eq[36][i] = IsEqual();
|
||||
eq[36][i].in[0] <== in[i];
|
||||
eq[36][i].in[1] <== 45;
|
||||
and[34][i] = AND();
|
||||
and[34][i].a <== states[i][13];
|
||||
and[34][i].b <== eq[36][i].out;
|
||||
multi_or[14][i] = MultiOR(4);
|
||||
multi_or[14][i].in[0] <== and[25][i].out;
|
||||
multi_or[14][i].in[1] <== and[29][i].out;
|
||||
multi_or[14][i].in[2] <== and[33][i].out;
|
||||
multi_or[14][i].in[3] <== and[34][i].out;
|
||||
states[i+1][7] <== multi_or[14][i].out;
|
||||
state_changed[i].in[6] <== states[i+1][7];
|
||||
eq[37][i] = IsEqual();
|
||||
eq[37][i].in[0] <== in[i];
|
||||
eq[37][i].in[1] <== 114;
|
||||
and[35][i] = AND();
|
||||
and[35][i].a <== states[i][6];
|
||||
and[35][i].b <== eq[37][i].out;
|
||||
states[i+1][8] <== and[35][i].out;
|
||||
state_changed[i].in[7] <== states[i+1][8];
|
||||
eq[38][i] = IsEqual();
|
||||
eq[38][i].in[0] <== in[i];
|
||||
eq[38][i].in[1] <== 64;
|
||||
and[36][i] = AND();
|
||||
and[36][i].a <== states[i][7];
|
||||
and[36][i].b <== eq[38][i].out;
|
||||
states[i+1][9] <== and[36][i].out;
|
||||
state_changed[i].in[8] <== states[i+1][9];
|
||||
eq[39][i] = IsEqual();
|
||||
eq[39][i].in[0] <== in[i];
|
||||
eq[39][i].in[1] <== 111;
|
||||
and[37][i] = AND();
|
||||
and[37][i].a <== states[i][8];
|
||||
and[37][i].b <== eq[39][i].out;
|
||||
states[i+1][10] <== and[37][i].out;
|
||||
state_changed[i].in[9] <== states[i+1][10];
|
||||
eq[40][i] = IsEqual();
|
||||
eq[40][i].in[0] <== in[i];
|
||||
eq[40][i].in[1] <== 109;
|
||||
and[38][i] = AND();
|
||||
and[38][i].a <== states[i][10];
|
||||
and[38][i].b <== eq[40][i].out;
|
||||
states[i+1][11] <== and[38][i].out;
|
||||
state_changed[i].in[10] <== states[i+1][11];
|
||||
eq[41][i] = IsEqual();
|
||||
eq[41][i].in[0] <== in[i];
|
||||
eq[41][i].in[1] <== 64;
|
||||
and[39][i] = AND();
|
||||
and[39][i].a <== states[i][1];
|
||||
and[39][i].b <== eq[41][i].out;
|
||||
states[i+1][12] <== and[39][i].out;
|
||||
state_changed[i].in[11] <== states[i+1][12];
|
||||
eq[42][i] = IsEqual();
|
||||
eq[42][i].in[0] <== in[i];
|
||||
eq[42][i].in[1] <== 58;
|
||||
and[40][i] = AND();
|
||||
and[40][i].a <== states[i][11];
|
||||
and[40][i].b <== eq[42][i].out;
|
||||
states[i+1][13] <== and[40][i].out;
|
||||
state_changed[i].in[12] <== states[i+1][13];
|
||||
lt[30][i] = LessThan(8);
|
||||
lt[30][i].in[0] <== 47;
|
||||
lt[30][i].in[1] <== in[i];
|
||||
lt[31][i] = LessThan(8);
|
||||
lt[31][i].in[0] <== in[i];
|
||||
lt[31][i].in[1] <== 58;
|
||||
and[41][i] = AND();
|
||||
and[41][i].a <== lt[30][i].out;
|
||||
and[41][i].b <== lt[31][i].out;
|
||||
lt[32][i] = LessThan(8);
|
||||
lt[32][i].in[0] <== 64;
|
||||
lt[32][i].in[1] <== in[i];
|
||||
lt[33][i] = LessThan(8);
|
||||
lt[33][i].in[0] <== in[i];
|
||||
lt[33][i].in[1] <== 91;
|
||||
and[42][i] = AND();
|
||||
and[42][i].a <== lt[32][i].out;
|
||||
and[42][i].b <== lt[33][i].out;
|
||||
lt[34][i] = LessThan(8);
|
||||
lt[34][i].in[0] <== 96;
|
||||
lt[34][i].in[1] <== in[i];
|
||||
lt[35][i] = LessThan(8);
|
||||
lt[35][i].in[0] <== in[i];
|
||||
lt[35][i].in[1] <== 123;
|
||||
and[43][i] = AND();
|
||||
and[43][i].a <== lt[34][i].out;
|
||||
and[43][i].b <== lt[35][i].out;
|
||||
eq[43][i] = IsEqual();
|
||||
eq[43][i].in[0] <== in[i];
|
||||
eq[43][i].in[1] <== 45;
|
||||
eq[44][i] = IsEqual();
|
||||
eq[44][i].in[0] <== in[i];
|
||||
eq[44][i].in[1] <== 46;
|
||||
eq[45][i] = IsEqual();
|
||||
eq[45][i].in[0] <== in[i];
|
||||
eq[45][i].in[1] <== 95;
|
||||
and[44][i] = AND();
|
||||
and[44][i].a <== states[i][9];
|
||||
multi_or[15][i] = MultiOR(6);
|
||||
multi_or[15][i].in[0] <== and[41][i].out;
|
||||
multi_or[15][i].in[1] <== and[42][i].out;
|
||||
multi_or[15][i].in[2] <== and[43][i].out;
|
||||
multi_or[15][i].in[3] <== eq[43][i].out;
|
||||
multi_or[15][i].in[4] <== eq[44][i].out;
|
||||
multi_or[15][i].in[5] <== eq[45][i].out;
|
||||
and[44][i].b <== multi_or[15][i].out;
|
||||
eq[46][i] = IsEqual();
|
||||
eq[46][i].in[0] <== in[i];
|
||||
eq[46][i].in[1] <== 45;
|
||||
and[45][i] = AND();
|
||||
and[45][i].a <== states[i][12];
|
||||
and[45][i].b <== eq[46][i].out;
|
||||
lt[36][i] = LessThan(8);
|
||||
lt[36][i].in[0] <== 47;
|
||||
lt[36][i].in[1] <== in[i];
|
||||
lt[37][i] = LessThan(8);
|
||||
lt[37][i].in[0] <== in[i];
|
||||
lt[37][i].in[1] <== 58;
|
||||
and[46][i] = AND();
|
||||
and[46][i].a <== lt[36][i].out;
|
||||
and[46][i].b <== lt[37][i].out;
|
||||
lt[38][i] = LessThan(8);
|
||||
lt[38][i].in[0] <== 64;
|
||||
lt[38][i].in[1] <== in[i];
|
||||
lt[39][i] = LessThan(8);
|
||||
lt[39][i].in[0] <== in[i];
|
||||
lt[39][i].in[1] <== 91;
|
||||
and[47][i] = AND();
|
||||
and[47][i].a <== lt[38][i].out;
|
||||
and[47][i].b <== lt[39][i].out;
|
||||
lt[40][i] = LessThan(8);
|
||||
lt[40][i].in[0] <== 96;
|
||||
lt[40][i].in[1] <== in[i];
|
||||
lt[41][i] = LessThan(8);
|
||||
lt[41][i].in[0] <== in[i];
|
||||
lt[41][i].in[1] <== 123;
|
||||
and[48][i] = AND();
|
||||
and[48][i].a <== lt[40][i].out;
|
||||
and[48][i].b <== lt[41][i].out;
|
||||
eq[47][i] = IsEqual();
|
||||
eq[47][i].in[0] <== in[i];
|
||||
eq[47][i].in[1] <== 45;
|
||||
eq[48][i] = IsEqual();
|
||||
eq[48][i].in[0] <== in[i];
|
||||
eq[48][i].in[1] <== 46;
|
||||
eq[49][i] = IsEqual();
|
||||
eq[49][i].in[0] <== in[i];
|
||||
eq[49][i].in[1] <== 95;
|
||||
and[49][i] = AND();
|
||||
and[49][i].a <== states[i][14];
|
||||
multi_or[16][i] = MultiOR(6);
|
||||
multi_or[16][i].in[0] <== and[46][i].out;
|
||||
multi_or[16][i].in[1] <== and[47][i].out;
|
||||
multi_or[16][i].in[2] <== and[48][i].out;
|
||||
multi_or[16][i].in[3] <== eq[47][i].out;
|
||||
multi_or[16][i].in[4] <== eq[48][i].out;
|
||||
multi_or[16][i].in[5] <== eq[49][i].out;
|
||||
and[49][i].b <== multi_or[16][i].out;
|
||||
eq[50][i] = IsEqual();
|
||||
eq[50][i].in[0] <== in[i];
|
||||
eq[50][i].in[1] <== 45;
|
||||
and[50][i] = AND();
|
||||
and[50][i].a <== states[i][15];
|
||||
and[50][i].b <== eq[50][i].out;
|
||||
multi_or[17][i] = MultiOR(4);
|
||||
multi_or[17][i].in[0] <== and[44][i].out;
|
||||
multi_or[17][i].in[1] <== and[45][i].out;
|
||||
multi_or[17][i].in[2] <== and[49][i].out;
|
||||
multi_or[17][i].in[3] <== and[50][i].out;
|
||||
states[i+1][14] <== multi_or[17][i].out;
|
||||
state_changed[i].in[13] <== states[i+1][14];
|
||||
lt[42][i] = LessThan(8);
|
||||
lt[42][i].in[0] <== 47;
|
||||
lt[42][i].in[1] <== in[i];
|
||||
lt[43][i] = LessThan(8);
|
||||
lt[43][i].in[0] <== in[i];
|
||||
lt[43][i].in[1] <== 58;
|
||||
and[51][i] = AND();
|
||||
and[51][i].a <== lt[42][i].out;
|
||||
and[51][i].b <== lt[43][i].out;
|
||||
lt[44][i] = LessThan(8);
|
||||
lt[44][i].in[0] <== 64;
|
||||
lt[44][i].in[1] <== in[i];
|
||||
lt[45][i] = LessThan(8);
|
||||
lt[45][i].in[0] <== in[i];
|
||||
lt[45][i].in[1] <== 91;
|
||||
and[52][i] = AND();
|
||||
and[52][i].a <== lt[44][i].out;
|
||||
and[52][i].b <== lt[45][i].out;
|
||||
lt[46][i] = LessThan(8);
|
||||
lt[46][i].in[0] <== 96;
|
||||
lt[46][i].in[1] <== in[i];
|
||||
lt[47][i] = LessThan(8);
|
||||
lt[47][i].in[0] <== in[i];
|
||||
lt[47][i].in[1] <== 123;
|
||||
and[53][i] = AND();
|
||||
and[53][i].a <== lt[46][i].out;
|
||||
and[53][i].b <== lt[47][i].out;
|
||||
eq[51][i] = IsEqual();
|
||||
eq[51][i].in[0] <== in[i];
|
||||
eq[51][i].in[1] <== 46;
|
||||
eq[52][i] = IsEqual();
|
||||
eq[52][i].in[0] <== in[i];
|
||||
eq[52][i].in[1] <== 95;
|
||||
and[54][i] = AND();
|
||||
and[54][i].a <== states[i][12];
|
||||
multi_or[18][i] = MultiOR(5);
|
||||
multi_or[18][i].in[0] <== and[51][i].out;
|
||||
multi_or[18][i].in[1] <== and[52][i].out;
|
||||
multi_or[18][i].in[2] <== and[53][i].out;
|
||||
multi_or[18][i].in[3] <== eq[51][i].out;
|
||||
multi_or[18][i].in[4] <== eq[52][i].out;
|
||||
and[54][i].b <== multi_or[18][i].out;
|
||||
lt[48][i] = LessThan(8);
|
||||
lt[48][i].in[0] <== 47;
|
||||
lt[48][i].in[1] <== in[i];
|
||||
lt[49][i] = LessThan(8);
|
||||
lt[49][i].in[0] <== in[i];
|
||||
lt[49][i].in[1] <== 58;
|
||||
and[55][i] = AND();
|
||||
and[55][i].a <== lt[48][i].out;
|
||||
and[55][i].b <== lt[49][i].out;
|
||||
lt[50][i] = LessThan(8);
|
||||
lt[50][i].in[0] <== 64;
|
||||
lt[50][i].in[1] <== in[i];
|
||||
lt[51][i] = LessThan(8);
|
||||
lt[51][i].in[0] <== in[i];
|
||||
lt[51][i].in[1] <== 91;
|
||||
and[56][i] = AND();
|
||||
and[56][i].a <== lt[50][i].out;
|
||||
and[56][i].b <== lt[51][i].out;
|
||||
lt[52][i] = LessThan(8);
|
||||
lt[52][i].in[0] <== 96;
|
||||
lt[52][i].in[1] <== in[i];
|
||||
lt[53][i] = LessThan(8);
|
||||
lt[53][i].in[0] <== in[i];
|
||||
lt[53][i].in[1] <== 123;
|
||||
and[57][i] = AND();
|
||||
and[57][i].a <== lt[52][i].out;
|
||||
and[57][i].b <== lt[53][i].out;
|
||||
eq[53][i] = IsEqual();
|
||||
eq[53][i].in[0] <== in[i];
|
||||
eq[53][i].in[1] <== 46;
|
||||
eq[54][i] = IsEqual();
|
||||
eq[54][i].in[0] <== in[i];
|
||||
eq[54][i].in[1] <== 95;
|
||||
and[58][i] = AND();
|
||||
and[58][i].a <== states[i][15];
|
||||
multi_or[19][i] = MultiOR(5);
|
||||
multi_or[19][i].in[0] <== and[55][i].out;
|
||||
multi_or[19][i].in[1] <== and[56][i].out;
|
||||
multi_or[19][i].in[2] <== and[57][i].out;
|
||||
multi_or[19][i].in[3] <== eq[53][i].out;
|
||||
multi_or[19][i].in[4] <== eq[54][i].out;
|
||||
and[58][i].b <== multi_or[19][i].out;
|
||||
multi_or[20][i] = MultiOR(2);
|
||||
multi_or[20][i].in[0] <== and[54][i].out;
|
||||
multi_or[20][i].in[1] <== and[58][i].out;
|
||||
states[i+1][15] <== multi_or[20][i].out;
|
||||
state_changed[i].in[14] <== states[i+1][15];
|
||||
eq[55][i] = IsEqual();
|
||||
eq[55][i].in[0] <== in[i];
|
||||
eq[55][i].in[1] <== 13;
|
||||
and[59][i] = AND();
|
||||
and[59][i].a <== states[i][14];
|
||||
and[59][i].b <== eq[55][i].out;
|
||||
eq[56][i] = IsEqual();
|
||||
eq[56][i].in[0] <== in[i];
|
||||
eq[56][i].in[1] <== 13;
|
||||
and[60][i] = AND();
|
||||
and[60][i].a <== states[i][15];
|
||||
and[60][i].b <== eq[56][i].out;
|
||||
eq[57][i] = IsEqual();
|
||||
eq[57][i].in[0] <== in[i];
|
||||
eq[57][i].in[1] <== 13;
|
||||
and[61][i] = AND();
|
||||
and[61][i].a <== states[i][17];
|
||||
and[61][i].b <== eq[57][i].out;
|
||||
multi_or[21][i] = MultiOR(3);
|
||||
multi_or[21][i].in[0] <== and[59][i].out;
|
||||
multi_or[21][i].in[1] <== and[60][i].out;
|
||||
multi_or[21][i].in[2] <== and[61][i].out;
|
||||
states[i+1][16] <== multi_or[21][i].out;
|
||||
state_changed[i].in[15] <== states[i+1][16];
|
||||
eq[58][i] = IsEqual();
|
||||
eq[58][i].in[0] <== in[i];
|
||||
eq[58][i].in[1] <== 62;
|
||||
and[62][i] = AND();
|
||||
and[62][i].a <== states[i][14];
|
||||
and[62][i].b <== eq[58][i].out;
|
||||
eq[59][i] = IsEqual();
|
||||
eq[59][i].in[0] <== in[i];
|
||||
eq[59][i].in[1] <== 62;
|
||||
and[63][i] = AND();
|
||||
and[63][i].a <== states[i][15];
|
||||
and[63][i].b <== eq[59][i].out;
|
||||
multi_or[22][i] = MultiOR(2);
|
||||
multi_or[22][i].in[0] <== and[62][i].out;
|
||||
multi_or[22][i].in[1] <== and[63][i].out;
|
||||
states[i+1][17] <== multi_or[22][i].out;
|
||||
state_changed[i].in[16] <== states[i+1][17];
|
||||
eq[60][i] = IsEqual();
|
||||
eq[60][i].in[0] <== in[i];
|
||||
eq[60][i].in[1] <== 10;
|
||||
and[64][i] = AND();
|
||||
and[64][i].a <== states[i][16];
|
||||
and[64][i].b <== eq[60][i].out;
|
||||
states[i+1][18] <== and[64][i].out;
|
||||
state_changed[i].in[17] <== states[i+1][18];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][18];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][18] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][15];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][9] * states[i+2][14];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][1] * states[i+2][1];
|
||||
is_substr0[i][3] <== is_substr0[i][2] + states[i+1][14] * states[i+2][14];
|
||||
is_substr0[i][4] <== is_substr0[i][3] + states[i+1][1] * states[i+2][12];
|
||||
is_substr0[i][5] <== is_substr0[i][4] + states[i+1][12] * states[i+2][15];
|
||||
is_substr0[i][6] <== is_substr0[i][5] + states[i+1][12] * states[i+2][14];
|
||||
is_substr0[i][7] <== is_substr0[i][6] + states[i+1][15] * states[i+2][14];
|
||||
is_substr0[i][8] <== is_substr0[i][7] + states[i+1][13] * states[i+2][1];
|
||||
is_substr0[i][9] <== is_substr0[i][8] + states[i+1][7] * states[i+2][9];
|
||||
is_substr0[i][10] <== is_substr0[i][9] + states[i+1][15] * states[i+2][15];
|
||||
is_substr0[i][11] <== is_substr0[i][10] + states[i+1][5] * states[i+2][7];
|
||||
is_substr0[i][12] <== is_substr0[i][11] + states[i+1][7] * states[i+2][7];
|
||||
is_substr0[i][13] <== is_substr0[i][12] + states[i+1][13] * states[i+2][7];
|
||||
is_substr0[i][14] <== is_substr0[i][13] + states[i+1][1] * states[i+2][7];
|
||||
is_reveal0[i] <== is_substr0[i][14] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
20
packages/circom/circuits/common/subject_all.json
Normal file
20
packages/circom/circuits/common/subject_all.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"max_byte_size": 1024,
|
||||
"parts": [
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "((\r\n)|^)subject:",
|
||||
"max_size": 10
|
||||
},
|
||||
{
|
||||
"is_public": true,
|
||||
"regex_def": "(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|\"|#|\\$|%|&|\\'|\\(|\\)|\\*|\\+|,|-|\\.|/|:|;|<|=|>|\\?|@|[|\\\\|]|\\^|_|`|{|\\||}|~| |\t)+",
|
||||
"max_size": 1024
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "\r\n",
|
||||
"max_size": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
338
packages/circom/circuits/common/subject_all_regex.circom
Normal file
338
packages/circom/circuits/common/subject_all_regex.circom
Normal file
@@ -0,0 +1,338 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template SubjectAllRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[48][num_bytes];
|
||||
component lt[4][num_bytes];
|
||||
component and[18][num_bytes];
|
||||
component multi_or[5][num_bytes];
|
||||
signal states[num_bytes+1][14];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 14; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(13);
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 47;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 127;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== lt[0][i].out;
|
||||
and[0][i].b <== lt[1][i].out;
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 9;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 32;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 33;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 34;
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 35;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 36;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 37;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 38;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 39;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 40;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 41;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 42;
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 43;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 44;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 45;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 46;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 47;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== states[i][1];
|
||||
multi_or[0][i] = MultiOR(18);
|
||||
multi_or[0][i].in[0] <== and[0][i].out;
|
||||
multi_or[0][i].in[1] <== eq[0][i].out;
|
||||
multi_or[0][i].in[2] <== eq[1][i].out;
|
||||
multi_or[0][i].in[3] <== eq[2][i].out;
|
||||
multi_or[0][i].in[4] <== eq[3][i].out;
|
||||
multi_or[0][i].in[5] <== eq[4][i].out;
|
||||
multi_or[0][i].in[6] <== eq[5][i].out;
|
||||
multi_or[0][i].in[7] <== eq[6][i].out;
|
||||
multi_or[0][i].in[8] <== eq[7][i].out;
|
||||
multi_or[0][i].in[9] <== eq[8][i].out;
|
||||
multi_or[0][i].in[10] <== eq[9][i].out;
|
||||
multi_or[0][i].in[11] <== eq[10][i].out;
|
||||
multi_or[0][i].in[12] <== eq[11][i].out;
|
||||
multi_or[0][i].in[13] <== eq[12][i].out;
|
||||
multi_or[0][i].in[14] <== eq[13][i].out;
|
||||
multi_or[0][i].in[15] <== eq[14][i].out;
|
||||
multi_or[0][i].in[16] <== eq[15][i].out;
|
||||
multi_or[0][i].in[17] <== eq[16][i].out;
|
||||
and[1][i].b <== multi_or[0][i].out;
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 47;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 127;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== lt[2][i].out;
|
||||
and[2][i].b <== lt[3][i].out;
|
||||
eq[17][i] = IsEqual();
|
||||
eq[17][i].in[0] <== in[i];
|
||||
eq[17][i].in[1] <== 9;
|
||||
eq[18][i] = IsEqual();
|
||||
eq[18][i].in[0] <== in[i];
|
||||
eq[18][i].in[1] <== 32;
|
||||
eq[19][i] = IsEqual();
|
||||
eq[19][i].in[0] <== in[i];
|
||||
eq[19][i].in[1] <== 33;
|
||||
eq[20][i] = IsEqual();
|
||||
eq[20][i].in[0] <== in[i];
|
||||
eq[20][i].in[1] <== 34;
|
||||
eq[21][i] = IsEqual();
|
||||
eq[21][i].in[0] <== in[i];
|
||||
eq[21][i].in[1] <== 35;
|
||||
eq[22][i] = IsEqual();
|
||||
eq[22][i].in[0] <== in[i];
|
||||
eq[22][i].in[1] <== 36;
|
||||
eq[23][i] = IsEqual();
|
||||
eq[23][i].in[0] <== in[i];
|
||||
eq[23][i].in[1] <== 37;
|
||||
eq[24][i] = IsEqual();
|
||||
eq[24][i].in[0] <== in[i];
|
||||
eq[24][i].in[1] <== 38;
|
||||
eq[25][i] = IsEqual();
|
||||
eq[25][i].in[0] <== in[i];
|
||||
eq[25][i].in[1] <== 39;
|
||||
eq[26][i] = IsEqual();
|
||||
eq[26][i].in[0] <== in[i];
|
||||
eq[26][i].in[1] <== 40;
|
||||
eq[27][i] = IsEqual();
|
||||
eq[27][i].in[0] <== in[i];
|
||||
eq[27][i].in[1] <== 41;
|
||||
eq[28][i] = IsEqual();
|
||||
eq[28][i].in[0] <== in[i];
|
||||
eq[28][i].in[1] <== 42;
|
||||
eq[29][i] = IsEqual();
|
||||
eq[29][i].in[0] <== in[i];
|
||||
eq[29][i].in[1] <== 43;
|
||||
eq[30][i] = IsEqual();
|
||||
eq[30][i].in[0] <== in[i];
|
||||
eq[30][i].in[1] <== 44;
|
||||
eq[31][i] = IsEqual();
|
||||
eq[31][i].in[0] <== in[i];
|
||||
eq[31][i].in[1] <== 45;
|
||||
eq[32][i] = IsEqual();
|
||||
eq[32][i].in[0] <== in[i];
|
||||
eq[32][i].in[1] <== 46;
|
||||
eq[33][i] = IsEqual();
|
||||
eq[33][i].in[0] <== in[i];
|
||||
eq[33][i].in[1] <== 47;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][13];
|
||||
multi_or[1][i] = MultiOR(18);
|
||||
multi_or[1][i].in[0] <== and[2][i].out;
|
||||
multi_or[1][i].in[1] <== eq[17][i].out;
|
||||
multi_or[1][i].in[2] <== eq[18][i].out;
|
||||
multi_or[1][i].in[3] <== eq[19][i].out;
|
||||
multi_or[1][i].in[4] <== eq[20][i].out;
|
||||
multi_or[1][i].in[5] <== eq[21][i].out;
|
||||
multi_or[1][i].in[6] <== eq[22][i].out;
|
||||
multi_or[1][i].in[7] <== eq[23][i].out;
|
||||
multi_or[1][i].in[8] <== eq[24][i].out;
|
||||
multi_or[1][i].in[9] <== eq[25][i].out;
|
||||
multi_or[1][i].in[10] <== eq[26][i].out;
|
||||
multi_or[1][i].in[11] <== eq[27][i].out;
|
||||
multi_or[1][i].in[12] <== eq[28][i].out;
|
||||
multi_or[1][i].in[13] <== eq[29][i].out;
|
||||
multi_or[1][i].in[14] <== eq[30][i].out;
|
||||
multi_or[1][i].in[15] <== eq[31][i].out;
|
||||
multi_or[1][i].in[16] <== eq[32][i].out;
|
||||
multi_or[1][i].in[17] <== eq[33][i].out;
|
||||
and[3][i].b <== multi_or[1][i].out;
|
||||
multi_or[2][i] = MultiOR(2);
|
||||
multi_or[2][i].in[0] <== and[1][i].out;
|
||||
multi_or[2][i].in[1] <== and[3][i].out;
|
||||
states[i+1][1] <== multi_or[2][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[34][i] = IsEqual();
|
||||
eq[34][i].in[0] <== in[i];
|
||||
eq[34][i].in[1] <== 13;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== states[i][0];
|
||||
and[4][i].b <== eq[34][i].out;
|
||||
eq[35][i] = IsEqual();
|
||||
eq[35][i].in[0] <== in[i];
|
||||
eq[35][i].in[1] <== 13;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== states[i][3];
|
||||
and[5][i].b <== eq[35][i].out;
|
||||
multi_or[3][i] = MultiOR(2);
|
||||
multi_or[3][i].in[0] <== and[4][i].out;
|
||||
multi_or[3][i].in[1] <== and[5][i].out;
|
||||
states[i+1][2] <== multi_or[3][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
eq[36][i] = IsEqual();
|
||||
eq[36][i].in[0] <== in[i];
|
||||
eq[36][i].in[1] <== 128;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== states[i][0];
|
||||
and[6][i].b <== eq[36][i].out;
|
||||
eq[37][i] = IsEqual();
|
||||
eq[37][i].in[0] <== in[i];
|
||||
eq[37][i].in[1] <== 10;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][2];
|
||||
and[7][i].b <== eq[37][i].out;
|
||||
multi_or[4][i] = MultiOR(2);
|
||||
multi_or[4][i].in[0] <== and[6][i].out;
|
||||
multi_or[4][i].in[1] <== and[7][i].out;
|
||||
states[i+1][3] <== multi_or[4][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
eq[38][i] = IsEqual();
|
||||
eq[38][i].in[0] <== in[i];
|
||||
eq[38][i].in[1] <== 13;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][1];
|
||||
and[8][i].b <== eq[38][i].out;
|
||||
states[i+1][4] <== and[8][i].out;
|
||||
state_changed[i].in[3] <== states[i+1][4];
|
||||
eq[39][i] = IsEqual();
|
||||
eq[39][i].in[0] <== in[i];
|
||||
eq[39][i].in[1] <== 115;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== states[i][3];
|
||||
and[9][i].b <== eq[39][i].out;
|
||||
states[i+1][5] <== and[9][i].out;
|
||||
state_changed[i].in[4] <== states[i+1][5];
|
||||
eq[40][i] = IsEqual();
|
||||
eq[40][i].in[0] <== in[i];
|
||||
eq[40][i].in[1] <== 117;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== states[i][5];
|
||||
and[10][i].b <== eq[40][i].out;
|
||||
states[i+1][6] <== and[10][i].out;
|
||||
state_changed[i].in[5] <== states[i+1][6];
|
||||
eq[41][i] = IsEqual();
|
||||
eq[41][i].in[0] <== in[i];
|
||||
eq[41][i].in[1] <== 98;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== states[i][6];
|
||||
and[11][i].b <== eq[41][i].out;
|
||||
states[i+1][7] <== and[11][i].out;
|
||||
state_changed[i].in[6] <== states[i+1][7];
|
||||
eq[42][i] = IsEqual();
|
||||
eq[42][i].in[0] <== in[i];
|
||||
eq[42][i].in[1] <== 10;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== states[i][4];
|
||||
and[12][i].b <== eq[42][i].out;
|
||||
states[i+1][8] <== and[12][i].out;
|
||||
state_changed[i].in[7] <== states[i+1][8];
|
||||
eq[43][i] = IsEqual();
|
||||
eq[43][i].in[0] <== in[i];
|
||||
eq[43][i].in[1] <== 106;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== states[i][7];
|
||||
and[13][i].b <== eq[43][i].out;
|
||||
states[i+1][9] <== and[13][i].out;
|
||||
state_changed[i].in[8] <== states[i+1][9];
|
||||
eq[44][i] = IsEqual();
|
||||
eq[44][i].in[0] <== in[i];
|
||||
eq[44][i].in[1] <== 101;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== states[i][9];
|
||||
and[14][i].b <== eq[44][i].out;
|
||||
states[i+1][10] <== and[14][i].out;
|
||||
state_changed[i].in[9] <== states[i+1][10];
|
||||
eq[45][i] = IsEqual();
|
||||
eq[45][i].in[0] <== in[i];
|
||||
eq[45][i].in[1] <== 99;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== states[i][10];
|
||||
and[15][i].b <== eq[45][i].out;
|
||||
states[i+1][11] <== and[15][i].out;
|
||||
state_changed[i].in[10] <== states[i+1][11];
|
||||
eq[46][i] = IsEqual();
|
||||
eq[46][i].in[0] <== in[i];
|
||||
eq[46][i].in[1] <== 116;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][11];
|
||||
and[16][i].b <== eq[46][i].out;
|
||||
states[i+1][12] <== and[16][i].out;
|
||||
state_changed[i].in[11] <== states[i+1][12];
|
||||
eq[47][i] = IsEqual();
|
||||
eq[47][i].in[0] <== in[i];
|
||||
eq[47][i].in[1] <== 58;
|
||||
and[17][i] = AND();
|
||||
and[17][i].a <== states[i][12];
|
||||
and[17][i].b <== eq[47][i].out;
|
||||
states[i+1][13] <== and[17][i].out;
|
||||
state_changed[i].in[12] <== states[i+1][13];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][8];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][8] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][3];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][13] * states[i+2][1];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][1] * states[i+2][1];
|
||||
is_reveal0[i] <== is_substr0[i][2] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
891
packages/circom/circuits/common/timestamp.circom
Normal file
891
packages/circom/circuits/common/timestamp.circom
Normal file
@@ -0,0 +1,891 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template TimestampRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[147][num_bytes];
|
||||
component lt[22][num_bytes];
|
||||
component and[43][num_bytes];
|
||||
component multi_or[9][num_bytes];
|
||||
signal states[num_bytes+1][25];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 25; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(24);
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 96;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 123;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== lt[0][i].out;
|
||||
and[0][i].b <== lt[1][i].out;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== states[i][1];
|
||||
and[1][i].b <== and[0][i].out;
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 97;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 98;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 99;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 100;
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 101;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 102;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 103;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 104;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 105;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 106;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 107;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 108;
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 109;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 110;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 111;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 112;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 113;
|
||||
eq[17][i] = IsEqual();
|
||||
eq[17][i].in[0] <== in[i];
|
||||
eq[17][i].in[1] <== 114;
|
||||
eq[18][i] = IsEqual();
|
||||
eq[18][i].in[0] <== in[i];
|
||||
eq[18][i].in[1] <== 115;
|
||||
eq[19][i] = IsEqual();
|
||||
eq[19][i].in[0] <== in[i];
|
||||
eq[19][i].in[1] <== 117;
|
||||
eq[20][i] = IsEqual();
|
||||
eq[20][i].in[0] <== in[i];
|
||||
eq[20][i].in[1] <== 118;
|
||||
eq[21][i] = IsEqual();
|
||||
eq[21][i].in[0] <== in[i];
|
||||
eq[21][i].in[1] <== 119;
|
||||
eq[22][i] = IsEqual();
|
||||
eq[22][i].in[0] <== in[i];
|
||||
eq[22][i].in[1] <== 120;
|
||||
eq[23][i] = IsEqual();
|
||||
eq[23][i].in[0] <== in[i];
|
||||
eq[23][i].in[1] <== 121;
|
||||
eq[24][i] = IsEqual();
|
||||
eq[24][i].in[0] <== in[i];
|
||||
eq[24][i].in[1] <== 122;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== states[i][14];
|
||||
multi_or[0][i] = MultiOR(25);
|
||||
multi_or[0][i].in[0] <== eq[0][i].out;
|
||||
multi_or[0][i].in[1] <== eq[1][i].out;
|
||||
multi_or[0][i].in[2] <== eq[2][i].out;
|
||||
multi_or[0][i].in[3] <== eq[3][i].out;
|
||||
multi_or[0][i].in[4] <== eq[4][i].out;
|
||||
multi_or[0][i].in[5] <== eq[5][i].out;
|
||||
multi_or[0][i].in[6] <== eq[6][i].out;
|
||||
multi_or[0][i].in[7] <== eq[7][i].out;
|
||||
multi_or[0][i].in[8] <== eq[8][i].out;
|
||||
multi_or[0][i].in[9] <== eq[9][i].out;
|
||||
multi_or[0][i].in[10] <== eq[10][i].out;
|
||||
multi_or[0][i].in[11] <== eq[11][i].out;
|
||||
multi_or[0][i].in[12] <== eq[12][i].out;
|
||||
multi_or[0][i].in[13] <== eq[13][i].out;
|
||||
multi_or[0][i].in[14] <== eq[14][i].out;
|
||||
multi_or[0][i].in[15] <== eq[15][i].out;
|
||||
multi_or[0][i].in[16] <== eq[16][i].out;
|
||||
multi_or[0][i].in[17] <== eq[17][i].out;
|
||||
multi_or[0][i].in[18] <== eq[18][i].out;
|
||||
multi_or[0][i].in[19] <== eq[19][i].out;
|
||||
multi_or[0][i].in[20] <== eq[20][i].out;
|
||||
multi_or[0][i].in[21] <== eq[21][i].out;
|
||||
multi_or[0][i].in[22] <== eq[22][i].out;
|
||||
multi_or[0][i].in[23] <== eq[23][i].out;
|
||||
multi_or[0][i].in[24] <== eq[24][i].out;
|
||||
and[2][i].b <== multi_or[0][i].out;
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 96;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 123;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== lt[2][i].out;
|
||||
and[3][i].b <== lt[3][i].out;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== states[i][16];
|
||||
and[4][i].b <== and[3][i].out;
|
||||
lt[4][i] = LessThan(8);
|
||||
lt[4][i].in[0] <== 96;
|
||||
lt[4][i].in[1] <== in[i];
|
||||
lt[5][i] = LessThan(8);
|
||||
lt[5][i].in[0] <== in[i];
|
||||
lt[5][i].in[1] <== 123;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== lt[4][i].out;
|
||||
and[5][i].b <== lt[5][i].out;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== states[i][22];
|
||||
and[6][i].b <== and[5][i].out;
|
||||
multi_or[1][i] = MultiOR(4);
|
||||
multi_or[1][i].in[0] <== and[1][i].out;
|
||||
multi_or[1][i].in[1] <== and[2][i].out;
|
||||
multi_or[1][i].in[2] <== and[4][i].out;
|
||||
multi_or[1][i].in[3] <== and[6][i].out;
|
||||
states[i+1][1] <== multi_or[1][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[25][i] = IsEqual();
|
||||
eq[25][i].in[0] <== in[i];
|
||||
eq[25][i].in[1] <== 61;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][1];
|
||||
and[7][i].b <== eq[25][i].out;
|
||||
states[i+1][2] <== and[7][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
eq[26][i] = IsEqual();
|
||||
eq[26][i].in[0] <== in[i];
|
||||
eq[26][i].in[1] <== 100;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][0];
|
||||
and[8][i].b <== eq[26][i].out;
|
||||
states[i+1][3] <== and[8][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
lt[6][i] = LessThan(8);
|
||||
lt[6][i].in[0] <== 47;
|
||||
lt[6][i].in[1] <== in[i];
|
||||
lt[7][i] = LessThan(8);
|
||||
lt[7][i].in[0] <== in[i];
|
||||
lt[7][i].in[1] <== 58;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== lt[6][i].out;
|
||||
and[9][i].b <== lt[7][i].out;
|
||||
lt[8][i] = LessThan(8);
|
||||
lt[8][i].in[0] <== 64;
|
||||
lt[8][i].in[1] <== in[i];
|
||||
lt[9][i] = LessThan(8);
|
||||
lt[9][i].in[0] <== in[i];
|
||||
lt[9][i].in[1] <== 127;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== lt[8][i].out;
|
||||
and[10][i].b <== lt[9][i].out;
|
||||
eq[27][i] = IsEqual();
|
||||
eq[27][i].in[0] <== in[i];
|
||||
eq[27][i].in[1] <== 9;
|
||||
eq[28][i] = IsEqual();
|
||||
eq[28][i].in[0] <== in[i];
|
||||
eq[28][i].in[1] <== 10;
|
||||
eq[29][i] = IsEqual();
|
||||
eq[29][i].in[0] <== in[i];
|
||||
eq[29][i].in[1] <== 13;
|
||||
eq[30][i] = IsEqual();
|
||||
eq[30][i].in[0] <== in[i];
|
||||
eq[30][i].in[1] <== 32;
|
||||
eq[31][i] = IsEqual();
|
||||
eq[31][i].in[0] <== in[i];
|
||||
eq[31][i].in[1] <== 33;
|
||||
eq[32][i] = IsEqual();
|
||||
eq[32][i].in[0] <== in[i];
|
||||
eq[32][i].in[1] <== 34;
|
||||
eq[33][i] = IsEqual();
|
||||
eq[33][i].in[0] <== in[i];
|
||||
eq[33][i].in[1] <== 35;
|
||||
eq[34][i] = IsEqual();
|
||||
eq[34][i].in[0] <== in[i];
|
||||
eq[34][i].in[1] <== 36;
|
||||
eq[35][i] = IsEqual();
|
||||
eq[35][i].in[0] <== in[i];
|
||||
eq[35][i].in[1] <== 37;
|
||||
eq[36][i] = IsEqual();
|
||||
eq[36][i].in[0] <== in[i];
|
||||
eq[36][i].in[1] <== 38;
|
||||
eq[37][i] = IsEqual();
|
||||
eq[37][i].in[0] <== in[i];
|
||||
eq[37][i].in[1] <== 39;
|
||||
eq[38][i] = IsEqual();
|
||||
eq[38][i].in[0] <== in[i];
|
||||
eq[38][i].in[1] <== 40;
|
||||
eq[39][i] = IsEqual();
|
||||
eq[39][i].in[0] <== in[i];
|
||||
eq[39][i].in[1] <== 41;
|
||||
eq[40][i] = IsEqual();
|
||||
eq[40][i].in[0] <== in[i];
|
||||
eq[40][i].in[1] <== 42;
|
||||
eq[41][i] = IsEqual();
|
||||
eq[41][i].in[0] <== in[i];
|
||||
eq[41][i].in[1] <== 43;
|
||||
eq[42][i] = IsEqual();
|
||||
eq[42][i].in[0] <== in[i];
|
||||
eq[42][i].in[1] <== 44;
|
||||
eq[43][i] = IsEqual();
|
||||
eq[43][i].in[0] <== in[i];
|
||||
eq[43][i].in[1] <== 45;
|
||||
eq[44][i] = IsEqual();
|
||||
eq[44][i].in[0] <== in[i];
|
||||
eq[44][i].in[1] <== 46;
|
||||
eq[45][i] = IsEqual();
|
||||
eq[45][i].in[0] <== in[i];
|
||||
eq[45][i].in[1] <== 47;
|
||||
eq[46][i] = IsEqual();
|
||||
eq[46][i].in[0] <== in[i];
|
||||
eq[46][i].in[1] <== 58;
|
||||
eq[47][i] = IsEqual();
|
||||
eq[47][i].in[0] <== in[i];
|
||||
eq[47][i].in[1] <== 60;
|
||||
eq[48][i] = IsEqual();
|
||||
eq[48][i].in[0] <== in[i];
|
||||
eq[48][i].in[1] <== 61;
|
||||
eq[49][i] = IsEqual();
|
||||
eq[49][i].in[0] <== in[i];
|
||||
eq[49][i].in[1] <== 62;
|
||||
eq[50][i] = IsEqual();
|
||||
eq[50][i].in[0] <== in[i];
|
||||
eq[50][i].in[1] <== 63;
|
||||
eq[51][i] = IsEqual();
|
||||
eq[51][i].in[0] <== in[i];
|
||||
eq[51][i].in[1] <== 64;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== states[i][2];
|
||||
multi_or[2][i] = MultiOR(27);
|
||||
multi_or[2][i].in[0] <== and[9][i].out;
|
||||
multi_or[2][i].in[1] <== and[10][i].out;
|
||||
multi_or[2][i].in[2] <== eq[27][i].out;
|
||||
multi_or[2][i].in[3] <== eq[28][i].out;
|
||||
multi_or[2][i].in[4] <== eq[29][i].out;
|
||||
multi_or[2][i].in[5] <== eq[30][i].out;
|
||||
multi_or[2][i].in[6] <== eq[31][i].out;
|
||||
multi_or[2][i].in[7] <== eq[32][i].out;
|
||||
multi_or[2][i].in[8] <== eq[33][i].out;
|
||||
multi_or[2][i].in[9] <== eq[34][i].out;
|
||||
multi_or[2][i].in[10] <== eq[35][i].out;
|
||||
multi_or[2][i].in[11] <== eq[36][i].out;
|
||||
multi_or[2][i].in[12] <== eq[37][i].out;
|
||||
multi_or[2][i].in[13] <== eq[38][i].out;
|
||||
multi_or[2][i].in[14] <== eq[39][i].out;
|
||||
multi_or[2][i].in[15] <== eq[40][i].out;
|
||||
multi_or[2][i].in[16] <== eq[41][i].out;
|
||||
multi_or[2][i].in[17] <== eq[42][i].out;
|
||||
multi_or[2][i].in[18] <== eq[43][i].out;
|
||||
multi_or[2][i].in[19] <== eq[44][i].out;
|
||||
multi_or[2][i].in[20] <== eq[45][i].out;
|
||||
multi_or[2][i].in[21] <== eq[46][i].out;
|
||||
multi_or[2][i].in[22] <== eq[47][i].out;
|
||||
multi_or[2][i].in[23] <== eq[48][i].out;
|
||||
multi_or[2][i].in[24] <== eq[49][i].out;
|
||||
multi_or[2][i].in[25] <== eq[50][i].out;
|
||||
multi_or[2][i].in[26] <== eq[51][i].out;
|
||||
and[11][i].b <== multi_or[2][i].out;
|
||||
lt[10][i] = LessThan(8);
|
||||
lt[10][i].in[0] <== 47;
|
||||
lt[10][i].in[1] <== in[i];
|
||||
lt[11][i] = LessThan(8);
|
||||
lt[11][i].in[0] <== in[i];
|
||||
lt[11][i].in[1] <== 58;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== lt[10][i].out;
|
||||
and[12][i].b <== lt[11][i].out;
|
||||
lt[12][i] = LessThan(8);
|
||||
lt[12][i].in[0] <== 64;
|
||||
lt[12][i].in[1] <== in[i];
|
||||
lt[13][i] = LessThan(8);
|
||||
lt[13][i].in[0] <== in[i];
|
||||
lt[13][i].in[1] <== 127;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== lt[12][i].out;
|
||||
and[13][i].b <== lt[13][i].out;
|
||||
eq[52][i] = IsEqual();
|
||||
eq[52][i].in[0] <== in[i];
|
||||
eq[52][i].in[1] <== 9;
|
||||
eq[53][i] = IsEqual();
|
||||
eq[53][i].in[0] <== in[i];
|
||||
eq[53][i].in[1] <== 10;
|
||||
eq[54][i] = IsEqual();
|
||||
eq[54][i].in[0] <== in[i];
|
||||
eq[54][i].in[1] <== 13;
|
||||
eq[55][i] = IsEqual();
|
||||
eq[55][i].in[0] <== in[i];
|
||||
eq[55][i].in[1] <== 32;
|
||||
eq[56][i] = IsEqual();
|
||||
eq[56][i].in[0] <== in[i];
|
||||
eq[56][i].in[1] <== 33;
|
||||
eq[57][i] = IsEqual();
|
||||
eq[57][i].in[0] <== in[i];
|
||||
eq[57][i].in[1] <== 34;
|
||||
eq[58][i] = IsEqual();
|
||||
eq[58][i].in[0] <== in[i];
|
||||
eq[58][i].in[1] <== 35;
|
||||
eq[59][i] = IsEqual();
|
||||
eq[59][i].in[0] <== in[i];
|
||||
eq[59][i].in[1] <== 36;
|
||||
eq[60][i] = IsEqual();
|
||||
eq[60][i].in[0] <== in[i];
|
||||
eq[60][i].in[1] <== 37;
|
||||
eq[61][i] = IsEqual();
|
||||
eq[61][i].in[0] <== in[i];
|
||||
eq[61][i].in[1] <== 38;
|
||||
eq[62][i] = IsEqual();
|
||||
eq[62][i].in[0] <== in[i];
|
||||
eq[62][i].in[1] <== 39;
|
||||
eq[63][i] = IsEqual();
|
||||
eq[63][i].in[0] <== in[i];
|
||||
eq[63][i].in[1] <== 40;
|
||||
eq[64][i] = IsEqual();
|
||||
eq[64][i].in[0] <== in[i];
|
||||
eq[64][i].in[1] <== 41;
|
||||
eq[65][i] = IsEqual();
|
||||
eq[65][i].in[0] <== in[i];
|
||||
eq[65][i].in[1] <== 42;
|
||||
eq[66][i] = IsEqual();
|
||||
eq[66][i].in[0] <== in[i];
|
||||
eq[66][i].in[1] <== 43;
|
||||
eq[67][i] = IsEqual();
|
||||
eq[67][i].in[0] <== in[i];
|
||||
eq[67][i].in[1] <== 44;
|
||||
eq[68][i] = IsEqual();
|
||||
eq[68][i].in[0] <== in[i];
|
||||
eq[68][i].in[1] <== 45;
|
||||
eq[69][i] = IsEqual();
|
||||
eq[69][i].in[0] <== in[i];
|
||||
eq[69][i].in[1] <== 46;
|
||||
eq[70][i] = IsEqual();
|
||||
eq[70][i].in[0] <== in[i];
|
||||
eq[70][i].in[1] <== 47;
|
||||
eq[71][i] = IsEqual();
|
||||
eq[71][i].in[0] <== in[i];
|
||||
eq[71][i].in[1] <== 58;
|
||||
eq[72][i] = IsEqual();
|
||||
eq[72][i].in[0] <== in[i];
|
||||
eq[72][i].in[1] <== 60;
|
||||
eq[73][i] = IsEqual();
|
||||
eq[73][i].in[0] <== in[i];
|
||||
eq[73][i].in[1] <== 61;
|
||||
eq[74][i] = IsEqual();
|
||||
eq[74][i].in[0] <== in[i];
|
||||
eq[74][i].in[1] <== 62;
|
||||
eq[75][i] = IsEqual();
|
||||
eq[75][i].in[0] <== in[i];
|
||||
eq[75][i].in[1] <== 63;
|
||||
eq[76][i] = IsEqual();
|
||||
eq[76][i].in[0] <== in[i];
|
||||
eq[76][i].in[1] <== 64;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== states[i][4];
|
||||
multi_or[3][i] = MultiOR(27);
|
||||
multi_or[3][i].in[0] <== and[12][i].out;
|
||||
multi_or[3][i].in[1] <== and[13][i].out;
|
||||
multi_or[3][i].in[2] <== eq[52][i].out;
|
||||
multi_or[3][i].in[3] <== eq[53][i].out;
|
||||
multi_or[3][i].in[4] <== eq[54][i].out;
|
||||
multi_or[3][i].in[5] <== eq[55][i].out;
|
||||
multi_or[3][i].in[6] <== eq[56][i].out;
|
||||
multi_or[3][i].in[7] <== eq[57][i].out;
|
||||
multi_or[3][i].in[8] <== eq[58][i].out;
|
||||
multi_or[3][i].in[9] <== eq[59][i].out;
|
||||
multi_or[3][i].in[10] <== eq[60][i].out;
|
||||
multi_or[3][i].in[11] <== eq[61][i].out;
|
||||
multi_or[3][i].in[12] <== eq[62][i].out;
|
||||
multi_or[3][i].in[13] <== eq[63][i].out;
|
||||
multi_or[3][i].in[14] <== eq[64][i].out;
|
||||
multi_or[3][i].in[15] <== eq[65][i].out;
|
||||
multi_or[3][i].in[16] <== eq[66][i].out;
|
||||
multi_or[3][i].in[17] <== eq[67][i].out;
|
||||
multi_or[3][i].in[18] <== eq[68][i].out;
|
||||
multi_or[3][i].in[19] <== eq[69][i].out;
|
||||
multi_or[3][i].in[20] <== eq[70][i].out;
|
||||
multi_or[3][i].in[21] <== eq[71][i].out;
|
||||
multi_or[3][i].in[22] <== eq[72][i].out;
|
||||
multi_or[3][i].in[23] <== eq[73][i].out;
|
||||
multi_or[3][i].in[24] <== eq[74][i].out;
|
||||
multi_or[3][i].in[25] <== eq[75][i].out;
|
||||
multi_or[3][i].in[26] <== eq[76][i].out;
|
||||
and[14][i].b <== multi_or[3][i].out;
|
||||
lt[14][i] = LessThan(8);
|
||||
lt[14][i].in[0] <== 64;
|
||||
lt[14][i].in[1] <== in[i];
|
||||
lt[15][i] = LessThan(8);
|
||||
lt[15][i].in[0] <== in[i];
|
||||
lt[15][i].in[1] <== 127;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== lt[14][i].out;
|
||||
and[15][i].b <== lt[15][i].out;
|
||||
eq[77][i] = IsEqual();
|
||||
eq[77][i].in[0] <== in[i];
|
||||
eq[77][i].in[1] <== 9;
|
||||
eq[78][i] = IsEqual();
|
||||
eq[78][i].in[0] <== in[i];
|
||||
eq[78][i].in[1] <== 10;
|
||||
eq[79][i] = IsEqual();
|
||||
eq[79][i].in[0] <== in[i];
|
||||
eq[79][i].in[1] <== 13;
|
||||
eq[80][i] = IsEqual();
|
||||
eq[80][i].in[0] <== in[i];
|
||||
eq[80][i].in[1] <== 32;
|
||||
eq[81][i] = IsEqual();
|
||||
eq[81][i].in[0] <== in[i];
|
||||
eq[81][i].in[1] <== 33;
|
||||
eq[82][i] = IsEqual();
|
||||
eq[82][i].in[0] <== in[i];
|
||||
eq[82][i].in[1] <== 34;
|
||||
eq[83][i] = IsEqual();
|
||||
eq[83][i].in[0] <== in[i];
|
||||
eq[83][i].in[1] <== 35;
|
||||
eq[84][i] = IsEqual();
|
||||
eq[84][i].in[0] <== in[i];
|
||||
eq[84][i].in[1] <== 36;
|
||||
eq[85][i] = IsEqual();
|
||||
eq[85][i].in[0] <== in[i];
|
||||
eq[85][i].in[1] <== 37;
|
||||
eq[86][i] = IsEqual();
|
||||
eq[86][i].in[0] <== in[i];
|
||||
eq[86][i].in[1] <== 38;
|
||||
eq[87][i] = IsEqual();
|
||||
eq[87][i].in[0] <== in[i];
|
||||
eq[87][i].in[1] <== 39;
|
||||
eq[88][i] = IsEqual();
|
||||
eq[88][i].in[0] <== in[i];
|
||||
eq[88][i].in[1] <== 40;
|
||||
eq[89][i] = IsEqual();
|
||||
eq[89][i].in[0] <== in[i];
|
||||
eq[89][i].in[1] <== 41;
|
||||
eq[90][i] = IsEqual();
|
||||
eq[90][i].in[0] <== in[i];
|
||||
eq[90][i].in[1] <== 42;
|
||||
eq[91][i] = IsEqual();
|
||||
eq[91][i].in[0] <== in[i];
|
||||
eq[91][i].in[1] <== 43;
|
||||
eq[92][i] = IsEqual();
|
||||
eq[92][i].in[0] <== in[i];
|
||||
eq[92][i].in[1] <== 44;
|
||||
eq[93][i] = IsEqual();
|
||||
eq[93][i].in[0] <== in[i];
|
||||
eq[93][i].in[1] <== 45;
|
||||
eq[94][i] = IsEqual();
|
||||
eq[94][i].in[0] <== in[i];
|
||||
eq[94][i].in[1] <== 46;
|
||||
eq[95][i] = IsEqual();
|
||||
eq[95][i].in[0] <== in[i];
|
||||
eq[95][i].in[1] <== 47;
|
||||
eq[96][i] = IsEqual();
|
||||
eq[96][i].in[0] <== in[i];
|
||||
eq[96][i].in[1] <== 58;
|
||||
eq[97][i] = IsEqual();
|
||||
eq[97][i].in[0] <== in[i];
|
||||
eq[97][i].in[1] <== 60;
|
||||
eq[98][i] = IsEqual();
|
||||
eq[98][i].in[0] <== in[i];
|
||||
eq[98][i].in[1] <== 61;
|
||||
eq[99][i] = IsEqual();
|
||||
eq[99][i].in[0] <== in[i];
|
||||
eq[99][i].in[1] <== 62;
|
||||
eq[100][i] = IsEqual();
|
||||
eq[100][i].in[0] <== in[i];
|
||||
eq[100][i].in[1] <== 63;
|
||||
eq[101][i] = IsEqual();
|
||||
eq[101][i].in[0] <== in[i];
|
||||
eq[101][i].in[1] <== 64;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][18];
|
||||
multi_or[4][i] = MultiOR(26);
|
||||
multi_or[4][i].in[0] <== and[15][i].out;
|
||||
multi_or[4][i].in[1] <== eq[77][i].out;
|
||||
multi_or[4][i].in[2] <== eq[78][i].out;
|
||||
multi_or[4][i].in[3] <== eq[79][i].out;
|
||||
multi_or[4][i].in[4] <== eq[80][i].out;
|
||||
multi_or[4][i].in[5] <== eq[81][i].out;
|
||||
multi_or[4][i].in[6] <== eq[82][i].out;
|
||||
multi_or[4][i].in[7] <== eq[83][i].out;
|
||||
multi_or[4][i].in[8] <== eq[84][i].out;
|
||||
multi_or[4][i].in[9] <== eq[85][i].out;
|
||||
multi_or[4][i].in[10] <== eq[86][i].out;
|
||||
multi_or[4][i].in[11] <== eq[87][i].out;
|
||||
multi_or[4][i].in[12] <== eq[88][i].out;
|
||||
multi_or[4][i].in[13] <== eq[89][i].out;
|
||||
multi_or[4][i].in[14] <== eq[90][i].out;
|
||||
multi_or[4][i].in[15] <== eq[91][i].out;
|
||||
multi_or[4][i].in[16] <== eq[92][i].out;
|
||||
multi_or[4][i].in[17] <== eq[93][i].out;
|
||||
multi_or[4][i].in[18] <== eq[94][i].out;
|
||||
multi_or[4][i].in[19] <== eq[95][i].out;
|
||||
multi_or[4][i].in[20] <== eq[96][i].out;
|
||||
multi_or[4][i].in[21] <== eq[97][i].out;
|
||||
multi_or[4][i].in[22] <== eq[98][i].out;
|
||||
multi_or[4][i].in[23] <== eq[99][i].out;
|
||||
multi_or[4][i].in[24] <== eq[100][i].out;
|
||||
multi_or[4][i].in[25] <== eq[101][i].out;
|
||||
and[16][i].b <== multi_or[4][i].out;
|
||||
lt[16][i] = LessThan(8);
|
||||
lt[16][i].in[0] <== 64;
|
||||
lt[16][i].in[1] <== in[i];
|
||||
lt[17][i] = LessThan(8);
|
||||
lt[17][i].in[0] <== in[i];
|
||||
lt[17][i].in[1] <== 127;
|
||||
and[17][i] = AND();
|
||||
and[17][i].a <== lt[16][i].out;
|
||||
and[17][i].b <== lt[17][i].out;
|
||||
eq[102][i] = IsEqual();
|
||||
eq[102][i].in[0] <== in[i];
|
||||
eq[102][i].in[1] <== 9;
|
||||
eq[103][i] = IsEqual();
|
||||
eq[103][i].in[0] <== in[i];
|
||||
eq[103][i].in[1] <== 10;
|
||||
eq[104][i] = IsEqual();
|
||||
eq[104][i].in[0] <== in[i];
|
||||
eq[104][i].in[1] <== 13;
|
||||
eq[105][i] = IsEqual();
|
||||
eq[105][i].in[0] <== in[i];
|
||||
eq[105][i].in[1] <== 32;
|
||||
eq[106][i] = IsEqual();
|
||||
eq[106][i].in[0] <== in[i];
|
||||
eq[106][i].in[1] <== 33;
|
||||
eq[107][i] = IsEqual();
|
||||
eq[107][i].in[0] <== in[i];
|
||||
eq[107][i].in[1] <== 34;
|
||||
eq[108][i] = IsEqual();
|
||||
eq[108][i].in[0] <== in[i];
|
||||
eq[108][i].in[1] <== 35;
|
||||
eq[109][i] = IsEqual();
|
||||
eq[109][i].in[0] <== in[i];
|
||||
eq[109][i].in[1] <== 36;
|
||||
eq[110][i] = IsEqual();
|
||||
eq[110][i].in[0] <== in[i];
|
||||
eq[110][i].in[1] <== 37;
|
||||
eq[111][i] = IsEqual();
|
||||
eq[111][i].in[0] <== in[i];
|
||||
eq[111][i].in[1] <== 38;
|
||||
eq[112][i] = IsEqual();
|
||||
eq[112][i].in[0] <== in[i];
|
||||
eq[112][i].in[1] <== 39;
|
||||
eq[113][i] = IsEqual();
|
||||
eq[113][i].in[0] <== in[i];
|
||||
eq[113][i].in[1] <== 40;
|
||||
eq[114][i] = IsEqual();
|
||||
eq[114][i].in[0] <== in[i];
|
||||
eq[114][i].in[1] <== 41;
|
||||
eq[115][i] = IsEqual();
|
||||
eq[115][i].in[0] <== in[i];
|
||||
eq[115][i].in[1] <== 42;
|
||||
eq[116][i] = IsEqual();
|
||||
eq[116][i].in[0] <== in[i];
|
||||
eq[116][i].in[1] <== 43;
|
||||
eq[117][i] = IsEqual();
|
||||
eq[117][i].in[0] <== in[i];
|
||||
eq[117][i].in[1] <== 44;
|
||||
eq[118][i] = IsEqual();
|
||||
eq[118][i].in[0] <== in[i];
|
||||
eq[118][i].in[1] <== 45;
|
||||
eq[119][i] = IsEqual();
|
||||
eq[119][i].in[0] <== in[i];
|
||||
eq[119][i].in[1] <== 46;
|
||||
eq[120][i] = IsEqual();
|
||||
eq[120][i].in[0] <== in[i];
|
||||
eq[120][i].in[1] <== 47;
|
||||
eq[121][i] = IsEqual();
|
||||
eq[121][i].in[0] <== in[i];
|
||||
eq[121][i].in[1] <== 58;
|
||||
eq[122][i] = IsEqual();
|
||||
eq[122][i].in[0] <== in[i];
|
||||
eq[122][i].in[1] <== 60;
|
||||
eq[123][i] = IsEqual();
|
||||
eq[123][i].in[0] <== in[i];
|
||||
eq[123][i].in[1] <== 61;
|
||||
eq[124][i] = IsEqual();
|
||||
eq[124][i].in[0] <== in[i];
|
||||
eq[124][i].in[1] <== 62;
|
||||
eq[125][i] = IsEqual();
|
||||
eq[125][i].in[0] <== in[i];
|
||||
eq[125][i].in[1] <== 63;
|
||||
eq[126][i] = IsEqual();
|
||||
eq[126][i].in[0] <== in[i];
|
||||
eq[126][i].in[1] <== 64;
|
||||
and[18][i] = AND();
|
||||
and[18][i].a <== states[i][23];
|
||||
multi_or[5][i] = MultiOR(26);
|
||||
multi_or[5][i].in[0] <== and[17][i].out;
|
||||
multi_or[5][i].in[1] <== eq[102][i].out;
|
||||
multi_or[5][i].in[2] <== eq[103][i].out;
|
||||
multi_or[5][i].in[3] <== eq[104][i].out;
|
||||
multi_or[5][i].in[4] <== eq[105][i].out;
|
||||
multi_or[5][i].in[5] <== eq[106][i].out;
|
||||
multi_or[5][i].in[6] <== eq[107][i].out;
|
||||
multi_or[5][i].in[7] <== eq[108][i].out;
|
||||
multi_or[5][i].in[8] <== eq[109][i].out;
|
||||
multi_or[5][i].in[9] <== eq[110][i].out;
|
||||
multi_or[5][i].in[10] <== eq[111][i].out;
|
||||
multi_or[5][i].in[11] <== eq[112][i].out;
|
||||
multi_or[5][i].in[12] <== eq[113][i].out;
|
||||
multi_or[5][i].in[13] <== eq[114][i].out;
|
||||
multi_or[5][i].in[14] <== eq[115][i].out;
|
||||
multi_or[5][i].in[15] <== eq[116][i].out;
|
||||
multi_or[5][i].in[16] <== eq[117][i].out;
|
||||
multi_or[5][i].in[17] <== eq[118][i].out;
|
||||
multi_or[5][i].in[18] <== eq[119][i].out;
|
||||
multi_or[5][i].in[19] <== eq[120][i].out;
|
||||
multi_or[5][i].in[20] <== eq[121][i].out;
|
||||
multi_or[5][i].in[21] <== eq[122][i].out;
|
||||
multi_or[5][i].in[22] <== eq[123][i].out;
|
||||
multi_or[5][i].in[23] <== eq[124][i].out;
|
||||
multi_or[5][i].in[24] <== eq[125][i].out;
|
||||
multi_or[5][i].in[25] <== eq[126][i].out;
|
||||
and[18][i].b <== multi_or[5][i].out;
|
||||
multi_or[6][i] = MultiOR(4);
|
||||
multi_or[6][i].in[0] <== and[11][i].out;
|
||||
multi_or[6][i].in[1] <== and[14][i].out;
|
||||
multi_or[6][i].in[2] <== and[16][i].out;
|
||||
multi_or[6][i].in[3] <== and[18][i].out;
|
||||
states[i+1][4] <== multi_or[6][i].out;
|
||||
state_changed[i].in[3] <== states[i+1][4];
|
||||
eq[127][i] = IsEqual();
|
||||
eq[127][i].in[0] <== in[i];
|
||||
eq[127][i].in[1] <== 107;
|
||||
and[19][i] = AND();
|
||||
and[19][i].a <== states[i][3];
|
||||
and[19][i].b <== eq[127][i].out;
|
||||
states[i+1][5] <== and[19][i].out;
|
||||
state_changed[i].in[4] <== states[i+1][5];
|
||||
eq[128][i] = IsEqual();
|
||||
eq[128][i].in[0] <== in[i];
|
||||
eq[128][i].in[1] <== 105;
|
||||
and[20][i] = AND();
|
||||
and[20][i].a <== states[i][5];
|
||||
and[20][i].b <== eq[128][i].out;
|
||||
states[i+1][6] <== and[20][i].out;
|
||||
state_changed[i].in[5] <== states[i+1][6];
|
||||
eq[129][i] = IsEqual();
|
||||
eq[129][i].in[0] <== in[i];
|
||||
eq[129][i].in[1] <== 109;
|
||||
and[21][i] = AND();
|
||||
and[21][i].a <== states[i][6];
|
||||
and[21][i].b <== eq[129][i].out;
|
||||
states[i+1][7] <== and[21][i].out;
|
||||
state_changed[i].in[6] <== states[i+1][7];
|
||||
eq[130][i] = IsEqual();
|
||||
eq[130][i].in[0] <== in[i];
|
||||
eq[130][i].in[1] <== 45;
|
||||
and[22][i] = AND();
|
||||
and[22][i].a <== states[i][7];
|
||||
and[22][i].b <== eq[130][i].out;
|
||||
states[i+1][8] <== and[22][i].out;
|
||||
state_changed[i].in[7] <== states[i+1][8];
|
||||
eq[131][i] = IsEqual();
|
||||
eq[131][i].in[0] <== in[i];
|
||||
eq[131][i].in[1] <== 115;
|
||||
and[23][i] = AND();
|
||||
and[23][i].a <== states[i][8];
|
||||
and[23][i].b <== eq[131][i].out;
|
||||
states[i+1][9] <== and[23][i].out;
|
||||
state_changed[i].in[8] <== states[i+1][9];
|
||||
eq[132][i] = IsEqual();
|
||||
eq[132][i].in[0] <== in[i];
|
||||
eq[132][i].in[1] <== 59;
|
||||
and[24][i] = AND();
|
||||
and[24][i].a <== states[i][4];
|
||||
and[24][i].b <== eq[132][i].out;
|
||||
states[i+1][10] <== and[24][i].out;
|
||||
state_changed[i].in[9] <== states[i+1][10];
|
||||
eq[133][i] = IsEqual();
|
||||
eq[133][i].in[0] <== in[i];
|
||||
eq[133][i].in[1] <== 105;
|
||||
and[25][i] = AND();
|
||||
and[25][i].a <== states[i][9];
|
||||
and[25][i].b <== eq[133][i].out;
|
||||
states[i+1][11] <== and[25][i].out;
|
||||
state_changed[i].in[10] <== states[i+1][11];
|
||||
eq[134][i] = IsEqual();
|
||||
eq[134][i].in[0] <== in[i];
|
||||
eq[134][i].in[1] <== 103;
|
||||
and[26][i] = AND();
|
||||
and[26][i].a <== states[i][11];
|
||||
and[26][i].b <== eq[134][i].out;
|
||||
states[i+1][12] <== and[26][i].out;
|
||||
state_changed[i].in[11] <== states[i+1][12];
|
||||
eq[135][i] = IsEqual();
|
||||
eq[135][i].in[0] <== in[i];
|
||||
eq[135][i].in[1] <== 110;
|
||||
and[27][i] = AND();
|
||||
and[27][i].a <== states[i][12];
|
||||
and[27][i].b <== eq[135][i].out;
|
||||
states[i+1][13] <== and[27][i].out;
|
||||
state_changed[i].in[12] <== states[i+1][13];
|
||||
eq[136][i] = IsEqual();
|
||||
eq[136][i].in[0] <== in[i];
|
||||
eq[136][i].in[1] <== 32;
|
||||
and[28][i] = AND();
|
||||
and[28][i].a <== states[i][10];
|
||||
and[28][i].b <== eq[136][i].out;
|
||||
eq[137][i] = IsEqual();
|
||||
eq[137][i].in[0] <== in[i];
|
||||
eq[137][i].in[1] <== 32;
|
||||
and[29][i] = AND();
|
||||
and[29][i].a <== states[i][24];
|
||||
and[29][i].b <== eq[137][i].out;
|
||||
multi_or[7][i] = MultiOR(2);
|
||||
multi_or[7][i].in[0] <== and[28][i].out;
|
||||
multi_or[7][i].in[1] <== and[29][i].out;
|
||||
states[i+1][14] <== multi_or[7][i].out;
|
||||
state_changed[i].in[13] <== states[i+1][14];
|
||||
eq[138][i] = IsEqual();
|
||||
eq[138][i].in[0] <== in[i];
|
||||
eq[138][i].in[1] <== 97;
|
||||
and[30][i] = AND();
|
||||
and[30][i].a <== states[i][13];
|
||||
and[30][i].b <== eq[138][i].out;
|
||||
states[i+1][15] <== and[30][i].out;
|
||||
state_changed[i].in[14] <== states[i+1][15];
|
||||
eq[139][i] = IsEqual();
|
||||
eq[139][i].in[0] <== in[i];
|
||||
eq[139][i].in[1] <== 116;
|
||||
and[31][i] = AND();
|
||||
and[31][i].a <== states[i][14];
|
||||
and[31][i].b <== eq[139][i].out;
|
||||
states[i+1][16] <== and[31][i].out;
|
||||
state_changed[i].in[15] <== states[i+1][16];
|
||||
eq[140][i] = IsEqual();
|
||||
eq[140][i].in[0] <== in[i];
|
||||
eq[140][i].in[1] <== 116;
|
||||
and[32][i] = AND();
|
||||
and[32][i].a <== states[i][15];
|
||||
and[32][i].b <== eq[140][i].out;
|
||||
states[i+1][17] <== and[32][i].out;
|
||||
state_changed[i].in[16] <== states[i+1][17];
|
||||
eq[141][i] = IsEqual();
|
||||
eq[141][i].in[0] <== in[i];
|
||||
eq[141][i].in[1] <== 61;
|
||||
and[33][i] = AND();
|
||||
and[33][i].a <== states[i][16];
|
||||
and[33][i].b <== eq[141][i].out;
|
||||
states[i+1][18] <== and[33][i].out;
|
||||
state_changed[i].in[17] <== states[i+1][18];
|
||||
eq[142][i] = IsEqual();
|
||||
eq[142][i].in[0] <== in[i];
|
||||
eq[142][i].in[1] <== 117;
|
||||
and[34][i] = AND();
|
||||
and[34][i].a <== states[i][17];
|
||||
and[34][i].b <== eq[142][i].out;
|
||||
states[i+1][19] <== and[34][i].out;
|
||||
state_changed[i].in[18] <== states[i+1][19];
|
||||
eq[143][i] = IsEqual();
|
||||
eq[143][i].in[0] <== in[i];
|
||||
eq[143][i].in[1] <== 114;
|
||||
and[35][i] = AND();
|
||||
and[35][i].a <== states[i][19];
|
||||
and[35][i].b <== eq[143][i].out;
|
||||
states[i+1][20] <== and[35][i].out;
|
||||
state_changed[i].in[19] <== states[i+1][20];
|
||||
eq[144][i] = IsEqual();
|
||||
eq[144][i].in[0] <== in[i];
|
||||
eq[144][i].in[1] <== 101;
|
||||
and[36][i] = AND();
|
||||
and[36][i].a <== states[i][20];
|
||||
and[36][i].b <== eq[144][i].out;
|
||||
states[i+1][21] <== and[36][i].out;
|
||||
state_changed[i].in[20] <== states[i+1][21];
|
||||
eq[145][i] = IsEqual();
|
||||
eq[145][i].in[0] <== in[i];
|
||||
eq[145][i].in[1] <== 58;
|
||||
and[37][i] = AND();
|
||||
and[37][i].a <== states[i][21];
|
||||
and[37][i].b <== eq[145][i].out;
|
||||
states[i+1][22] <== and[37][i].out;
|
||||
state_changed[i].in[21] <== states[i+1][22];
|
||||
lt[18][i] = LessThan(8);
|
||||
lt[18][i].in[0] <== 47;
|
||||
lt[18][i].in[1] <== in[i];
|
||||
lt[19][i] = LessThan(8);
|
||||
lt[19][i].in[0] <== in[i];
|
||||
lt[19][i].in[1] <== 58;
|
||||
and[38][i] = AND();
|
||||
and[38][i].a <== lt[18][i].out;
|
||||
and[38][i].b <== lt[19][i].out;
|
||||
and[39][i] = AND();
|
||||
and[39][i].a <== states[i][18];
|
||||
and[39][i].b <== and[38][i].out;
|
||||
lt[20][i] = LessThan(8);
|
||||
lt[20][i].in[0] <== 47;
|
||||
lt[20][i].in[1] <== in[i];
|
||||
lt[21][i] = LessThan(8);
|
||||
lt[21][i].in[0] <== in[i];
|
||||
lt[21][i].in[1] <== 58;
|
||||
and[40][i] = AND();
|
||||
and[40][i].a <== lt[20][i].out;
|
||||
and[40][i].b <== lt[21][i].out;
|
||||
and[41][i] = AND();
|
||||
and[41][i].a <== states[i][23];
|
||||
and[41][i].b <== and[40][i].out;
|
||||
multi_or[8][i] = MultiOR(2);
|
||||
multi_or[8][i].in[0] <== and[39][i].out;
|
||||
multi_or[8][i].in[1] <== and[41][i].out;
|
||||
states[i+1][23] <== multi_or[8][i].out;
|
||||
state_changed[i].in[22] <== states[i+1][23];
|
||||
eq[146][i] = IsEqual();
|
||||
eq[146][i].in[0] <== in[i];
|
||||
eq[146][i].in[1] <== 59;
|
||||
and[42][i] = AND();
|
||||
and[42][i].a <== states[i][23];
|
||||
and[42][i].b <== eq[146][i].out;
|
||||
states[i+1][24] <== and[42][i].out;
|
||||
state_changed[i].in[23] <== states[i+1][24];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][24];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][24] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][3];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][23] * states[i+2][23];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][18] * states[i+2][23];
|
||||
is_reveal0[i] <== is_substr0[i][2] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
25
packages/circom/circuits/common/timestamp.json
Normal file
25
packages/circom/circuits/common/timestamp.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"max_byte_size": 1024,
|
||||
"parts": [
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "dkim-signature:",
|
||||
"max_size": 15
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": "((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)+=(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|\"|#|$|%|&|\\'|\\(|\\)|\\*|\\+|,|-|\\.|\\/|:|<|=|>|\\?|@|\\[|\\\\|\\]|\\^|_|`|{|\\||}|~| |\t|\n|\r|\\x0b|\\x0c)+; )+t=",
|
||||
"max_size": 128
|
||||
},
|
||||
{
|
||||
"is_public": true,
|
||||
"regex_def": "(0|1|2|3|4|5|6|7|8|9)+",
|
||||
"max_size": 10
|
||||
},
|
||||
{
|
||||
"is_public": false,
|
||||
"regex_def": ";",
|
||||
"max_size": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
865
packages/circom/circuits/common/timestamp_regex.circom
Normal file
865
packages/circom/circuits/common/timestamp_regex.circom
Normal file
@@ -0,0 +1,865 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template TimestampRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[147][num_bytes];
|
||||
component lt[18][num_bytes];
|
||||
component and[39][num_bytes];
|
||||
component multi_or[9][num_bytes];
|
||||
signal states[num_bytes+1][25];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 25; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(24);
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 97;
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 98;
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 99;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 100;
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 101;
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 102;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 103;
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 104;
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 105;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 106;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 107;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 108;
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 109;
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 110;
|
||||
eq[14][i] = IsEqual();
|
||||
eq[14][i].in[0] <== in[i];
|
||||
eq[14][i].in[1] <== 111;
|
||||
eq[15][i] = IsEqual();
|
||||
eq[15][i].in[0] <== in[i];
|
||||
eq[15][i].in[1] <== 112;
|
||||
eq[16][i] = IsEqual();
|
||||
eq[16][i].in[0] <== in[i];
|
||||
eq[16][i].in[1] <== 113;
|
||||
eq[17][i] = IsEqual();
|
||||
eq[17][i].in[0] <== in[i];
|
||||
eq[17][i].in[1] <== 114;
|
||||
eq[18][i] = IsEqual();
|
||||
eq[18][i].in[0] <== in[i];
|
||||
eq[18][i].in[1] <== 115;
|
||||
eq[19][i] = IsEqual();
|
||||
eq[19][i].in[0] <== in[i];
|
||||
eq[19][i].in[1] <== 117;
|
||||
eq[20][i] = IsEqual();
|
||||
eq[20][i].in[0] <== in[i];
|
||||
eq[20][i].in[1] <== 118;
|
||||
eq[21][i] = IsEqual();
|
||||
eq[21][i].in[0] <== in[i];
|
||||
eq[21][i].in[1] <== 119;
|
||||
eq[22][i] = IsEqual();
|
||||
eq[22][i].in[0] <== in[i];
|
||||
eq[22][i].in[1] <== 120;
|
||||
eq[23][i] = IsEqual();
|
||||
eq[23][i].in[0] <== in[i];
|
||||
eq[23][i].in[1] <== 121;
|
||||
eq[24][i] = IsEqual();
|
||||
eq[24][i].in[0] <== in[i];
|
||||
eq[24][i].in[1] <== 122;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== states[i][13];
|
||||
multi_or[0][i] = MultiOR(25);
|
||||
multi_or[0][i].in[0] <== eq[0][i].out;
|
||||
multi_or[0][i].in[1] <== eq[1][i].out;
|
||||
multi_or[0][i].in[2] <== eq[2][i].out;
|
||||
multi_or[0][i].in[3] <== eq[3][i].out;
|
||||
multi_or[0][i].in[4] <== eq[4][i].out;
|
||||
multi_or[0][i].in[5] <== eq[5][i].out;
|
||||
multi_or[0][i].in[6] <== eq[6][i].out;
|
||||
multi_or[0][i].in[7] <== eq[7][i].out;
|
||||
multi_or[0][i].in[8] <== eq[8][i].out;
|
||||
multi_or[0][i].in[9] <== eq[9][i].out;
|
||||
multi_or[0][i].in[10] <== eq[10][i].out;
|
||||
multi_or[0][i].in[11] <== eq[11][i].out;
|
||||
multi_or[0][i].in[12] <== eq[12][i].out;
|
||||
multi_or[0][i].in[13] <== eq[13][i].out;
|
||||
multi_or[0][i].in[14] <== eq[14][i].out;
|
||||
multi_or[0][i].in[15] <== eq[15][i].out;
|
||||
multi_or[0][i].in[16] <== eq[16][i].out;
|
||||
multi_or[0][i].in[17] <== eq[17][i].out;
|
||||
multi_or[0][i].in[18] <== eq[18][i].out;
|
||||
multi_or[0][i].in[19] <== eq[19][i].out;
|
||||
multi_or[0][i].in[20] <== eq[20][i].out;
|
||||
multi_or[0][i].in[21] <== eq[21][i].out;
|
||||
multi_or[0][i].in[22] <== eq[22][i].out;
|
||||
multi_or[0][i].in[23] <== eq[23][i].out;
|
||||
multi_or[0][i].in[24] <== eq[24][i].out;
|
||||
and[0][i].b <== multi_or[0][i].out;
|
||||
lt[0][i] = LessThan(8);
|
||||
lt[0][i].in[0] <== 96;
|
||||
lt[0][i].in[1] <== in[i];
|
||||
lt[1][i] = LessThan(8);
|
||||
lt[1][i].in[0] <== in[i];
|
||||
lt[1][i].in[1] <== 123;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== lt[0][i].out;
|
||||
and[1][i].b <== lt[1][i].out;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== states[i][23];
|
||||
and[2][i].b <== and[1][i].out;
|
||||
multi_or[1][i] = MultiOR(2);
|
||||
multi_or[1][i].in[0] <== and[0][i].out;
|
||||
multi_or[1][i].in[1] <== and[2][i].out;
|
||||
states[i+1][1] <== multi_or[1][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[25][i] = IsEqual();
|
||||
eq[25][i].in[0] <== in[i];
|
||||
eq[25][i].in[1] <== 61;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][1];
|
||||
and[3][i].b <== eq[25][i].out;
|
||||
states[i+1][2] <== and[3][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
lt[2][i] = LessThan(8);
|
||||
lt[2][i].in[0] <== 47;
|
||||
lt[2][i].in[1] <== in[i];
|
||||
lt[3][i] = LessThan(8);
|
||||
lt[3][i].in[0] <== in[i];
|
||||
lt[3][i].in[1] <== 58;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== lt[2][i].out;
|
||||
and[4][i].b <== lt[3][i].out;
|
||||
lt[4][i] = LessThan(8);
|
||||
lt[4][i].in[0] <== 64;
|
||||
lt[4][i].in[1] <== in[i];
|
||||
lt[5][i] = LessThan(8);
|
||||
lt[5][i].in[0] <== in[i];
|
||||
lt[5][i].in[1] <== 127;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== lt[4][i].out;
|
||||
and[5][i].b <== lt[5][i].out;
|
||||
eq[26][i] = IsEqual();
|
||||
eq[26][i].in[0] <== in[i];
|
||||
eq[26][i].in[1] <== 9;
|
||||
eq[27][i] = IsEqual();
|
||||
eq[27][i].in[0] <== in[i];
|
||||
eq[27][i].in[1] <== 10;
|
||||
eq[28][i] = IsEqual();
|
||||
eq[28][i].in[0] <== in[i];
|
||||
eq[28][i].in[1] <== 13;
|
||||
eq[29][i] = IsEqual();
|
||||
eq[29][i].in[0] <== in[i];
|
||||
eq[29][i].in[1] <== 32;
|
||||
eq[30][i] = IsEqual();
|
||||
eq[30][i].in[0] <== in[i];
|
||||
eq[30][i].in[1] <== 33;
|
||||
eq[31][i] = IsEqual();
|
||||
eq[31][i].in[0] <== in[i];
|
||||
eq[31][i].in[1] <== 34;
|
||||
eq[32][i] = IsEqual();
|
||||
eq[32][i].in[0] <== in[i];
|
||||
eq[32][i].in[1] <== 35;
|
||||
eq[33][i] = IsEqual();
|
||||
eq[33][i].in[0] <== in[i];
|
||||
eq[33][i].in[1] <== 36;
|
||||
eq[34][i] = IsEqual();
|
||||
eq[34][i].in[0] <== in[i];
|
||||
eq[34][i].in[1] <== 37;
|
||||
eq[35][i] = IsEqual();
|
||||
eq[35][i].in[0] <== in[i];
|
||||
eq[35][i].in[1] <== 38;
|
||||
eq[36][i] = IsEqual();
|
||||
eq[36][i].in[0] <== in[i];
|
||||
eq[36][i].in[1] <== 39;
|
||||
eq[37][i] = IsEqual();
|
||||
eq[37][i].in[0] <== in[i];
|
||||
eq[37][i].in[1] <== 40;
|
||||
eq[38][i] = IsEqual();
|
||||
eq[38][i].in[0] <== in[i];
|
||||
eq[38][i].in[1] <== 41;
|
||||
eq[39][i] = IsEqual();
|
||||
eq[39][i].in[0] <== in[i];
|
||||
eq[39][i].in[1] <== 42;
|
||||
eq[40][i] = IsEqual();
|
||||
eq[40][i].in[0] <== in[i];
|
||||
eq[40][i].in[1] <== 43;
|
||||
eq[41][i] = IsEqual();
|
||||
eq[41][i].in[0] <== in[i];
|
||||
eq[41][i].in[1] <== 44;
|
||||
eq[42][i] = IsEqual();
|
||||
eq[42][i].in[0] <== in[i];
|
||||
eq[42][i].in[1] <== 45;
|
||||
eq[43][i] = IsEqual();
|
||||
eq[43][i].in[0] <== in[i];
|
||||
eq[43][i].in[1] <== 46;
|
||||
eq[44][i] = IsEqual();
|
||||
eq[44][i].in[0] <== in[i];
|
||||
eq[44][i].in[1] <== 47;
|
||||
eq[45][i] = IsEqual();
|
||||
eq[45][i].in[0] <== in[i];
|
||||
eq[45][i].in[1] <== 58;
|
||||
eq[46][i] = IsEqual();
|
||||
eq[46][i].in[0] <== in[i];
|
||||
eq[46][i].in[1] <== 60;
|
||||
eq[47][i] = IsEqual();
|
||||
eq[47][i].in[0] <== in[i];
|
||||
eq[47][i].in[1] <== 61;
|
||||
eq[48][i] = IsEqual();
|
||||
eq[48][i].in[0] <== in[i];
|
||||
eq[48][i].in[1] <== 62;
|
||||
eq[49][i] = IsEqual();
|
||||
eq[49][i].in[0] <== in[i];
|
||||
eq[49][i].in[1] <== 63;
|
||||
eq[50][i] = IsEqual();
|
||||
eq[50][i].in[0] <== in[i];
|
||||
eq[50][i].in[1] <== 64;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== states[i][2];
|
||||
multi_or[2][i] = MultiOR(27);
|
||||
multi_or[2][i].in[0] <== and[4][i].out;
|
||||
multi_or[2][i].in[1] <== and[5][i].out;
|
||||
multi_or[2][i].in[2] <== eq[26][i].out;
|
||||
multi_or[2][i].in[3] <== eq[27][i].out;
|
||||
multi_or[2][i].in[4] <== eq[28][i].out;
|
||||
multi_or[2][i].in[5] <== eq[29][i].out;
|
||||
multi_or[2][i].in[6] <== eq[30][i].out;
|
||||
multi_or[2][i].in[7] <== eq[31][i].out;
|
||||
multi_or[2][i].in[8] <== eq[32][i].out;
|
||||
multi_or[2][i].in[9] <== eq[33][i].out;
|
||||
multi_or[2][i].in[10] <== eq[34][i].out;
|
||||
multi_or[2][i].in[11] <== eq[35][i].out;
|
||||
multi_or[2][i].in[12] <== eq[36][i].out;
|
||||
multi_or[2][i].in[13] <== eq[37][i].out;
|
||||
multi_or[2][i].in[14] <== eq[38][i].out;
|
||||
multi_or[2][i].in[15] <== eq[39][i].out;
|
||||
multi_or[2][i].in[16] <== eq[40][i].out;
|
||||
multi_or[2][i].in[17] <== eq[41][i].out;
|
||||
multi_or[2][i].in[18] <== eq[42][i].out;
|
||||
multi_or[2][i].in[19] <== eq[43][i].out;
|
||||
multi_or[2][i].in[20] <== eq[44][i].out;
|
||||
multi_or[2][i].in[21] <== eq[45][i].out;
|
||||
multi_or[2][i].in[22] <== eq[46][i].out;
|
||||
multi_or[2][i].in[23] <== eq[47][i].out;
|
||||
multi_or[2][i].in[24] <== eq[48][i].out;
|
||||
multi_or[2][i].in[25] <== eq[49][i].out;
|
||||
multi_or[2][i].in[26] <== eq[50][i].out;
|
||||
and[6][i].b <== multi_or[2][i].out;
|
||||
lt[6][i] = LessThan(8);
|
||||
lt[6][i].in[0] <== 47;
|
||||
lt[6][i].in[1] <== in[i];
|
||||
lt[7][i] = LessThan(8);
|
||||
lt[7][i].in[0] <== in[i];
|
||||
lt[7][i].in[1] <== 58;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== lt[6][i].out;
|
||||
and[7][i].b <== lt[7][i].out;
|
||||
lt[8][i] = LessThan(8);
|
||||
lt[8][i].in[0] <== 64;
|
||||
lt[8][i].in[1] <== in[i];
|
||||
lt[9][i] = LessThan(8);
|
||||
lt[9][i].in[0] <== in[i];
|
||||
lt[9][i].in[1] <== 127;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== lt[8][i].out;
|
||||
and[8][i].b <== lt[9][i].out;
|
||||
eq[51][i] = IsEqual();
|
||||
eq[51][i].in[0] <== in[i];
|
||||
eq[51][i].in[1] <== 9;
|
||||
eq[52][i] = IsEqual();
|
||||
eq[52][i].in[0] <== in[i];
|
||||
eq[52][i].in[1] <== 10;
|
||||
eq[53][i] = IsEqual();
|
||||
eq[53][i].in[0] <== in[i];
|
||||
eq[53][i].in[1] <== 13;
|
||||
eq[54][i] = IsEqual();
|
||||
eq[54][i].in[0] <== in[i];
|
||||
eq[54][i].in[1] <== 32;
|
||||
eq[55][i] = IsEqual();
|
||||
eq[55][i].in[0] <== in[i];
|
||||
eq[55][i].in[1] <== 33;
|
||||
eq[56][i] = IsEqual();
|
||||
eq[56][i].in[0] <== in[i];
|
||||
eq[56][i].in[1] <== 34;
|
||||
eq[57][i] = IsEqual();
|
||||
eq[57][i].in[0] <== in[i];
|
||||
eq[57][i].in[1] <== 35;
|
||||
eq[58][i] = IsEqual();
|
||||
eq[58][i].in[0] <== in[i];
|
||||
eq[58][i].in[1] <== 36;
|
||||
eq[59][i] = IsEqual();
|
||||
eq[59][i].in[0] <== in[i];
|
||||
eq[59][i].in[1] <== 37;
|
||||
eq[60][i] = IsEqual();
|
||||
eq[60][i].in[0] <== in[i];
|
||||
eq[60][i].in[1] <== 38;
|
||||
eq[61][i] = IsEqual();
|
||||
eq[61][i].in[0] <== in[i];
|
||||
eq[61][i].in[1] <== 39;
|
||||
eq[62][i] = IsEqual();
|
||||
eq[62][i].in[0] <== in[i];
|
||||
eq[62][i].in[1] <== 40;
|
||||
eq[63][i] = IsEqual();
|
||||
eq[63][i].in[0] <== in[i];
|
||||
eq[63][i].in[1] <== 41;
|
||||
eq[64][i] = IsEqual();
|
||||
eq[64][i].in[0] <== in[i];
|
||||
eq[64][i].in[1] <== 42;
|
||||
eq[65][i] = IsEqual();
|
||||
eq[65][i].in[0] <== in[i];
|
||||
eq[65][i].in[1] <== 43;
|
||||
eq[66][i] = IsEqual();
|
||||
eq[66][i].in[0] <== in[i];
|
||||
eq[66][i].in[1] <== 44;
|
||||
eq[67][i] = IsEqual();
|
||||
eq[67][i].in[0] <== in[i];
|
||||
eq[67][i].in[1] <== 45;
|
||||
eq[68][i] = IsEqual();
|
||||
eq[68][i].in[0] <== in[i];
|
||||
eq[68][i].in[1] <== 46;
|
||||
eq[69][i] = IsEqual();
|
||||
eq[69][i].in[0] <== in[i];
|
||||
eq[69][i].in[1] <== 47;
|
||||
eq[70][i] = IsEqual();
|
||||
eq[70][i].in[0] <== in[i];
|
||||
eq[70][i].in[1] <== 58;
|
||||
eq[71][i] = IsEqual();
|
||||
eq[71][i].in[0] <== in[i];
|
||||
eq[71][i].in[1] <== 60;
|
||||
eq[72][i] = IsEqual();
|
||||
eq[72][i].in[0] <== in[i];
|
||||
eq[72][i].in[1] <== 61;
|
||||
eq[73][i] = IsEqual();
|
||||
eq[73][i].in[0] <== in[i];
|
||||
eq[73][i].in[1] <== 62;
|
||||
eq[74][i] = IsEqual();
|
||||
eq[74][i].in[0] <== in[i];
|
||||
eq[74][i].in[1] <== 63;
|
||||
eq[75][i] = IsEqual();
|
||||
eq[75][i].in[0] <== in[i];
|
||||
eq[75][i].in[1] <== 64;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== states[i][3];
|
||||
multi_or[3][i] = MultiOR(27);
|
||||
multi_or[3][i].in[0] <== and[7][i].out;
|
||||
multi_or[3][i].in[1] <== and[8][i].out;
|
||||
multi_or[3][i].in[2] <== eq[51][i].out;
|
||||
multi_or[3][i].in[3] <== eq[52][i].out;
|
||||
multi_or[3][i].in[4] <== eq[53][i].out;
|
||||
multi_or[3][i].in[5] <== eq[54][i].out;
|
||||
multi_or[3][i].in[6] <== eq[55][i].out;
|
||||
multi_or[3][i].in[7] <== eq[56][i].out;
|
||||
multi_or[3][i].in[8] <== eq[57][i].out;
|
||||
multi_or[3][i].in[9] <== eq[58][i].out;
|
||||
multi_or[3][i].in[10] <== eq[59][i].out;
|
||||
multi_or[3][i].in[11] <== eq[60][i].out;
|
||||
multi_or[3][i].in[12] <== eq[61][i].out;
|
||||
multi_or[3][i].in[13] <== eq[62][i].out;
|
||||
multi_or[3][i].in[14] <== eq[63][i].out;
|
||||
multi_or[3][i].in[15] <== eq[64][i].out;
|
||||
multi_or[3][i].in[16] <== eq[65][i].out;
|
||||
multi_or[3][i].in[17] <== eq[66][i].out;
|
||||
multi_or[3][i].in[18] <== eq[67][i].out;
|
||||
multi_or[3][i].in[19] <== eq[68][i].out;
|
||||
multi_or[3][i].in[20] <== eq[69][i].out;
|
||||
multi_or[3][i].in[21] <== eq[70][i].out;
|
||||
multi_or[3][i].in[22] <== eq[71][i].out;
|
||||
multi_or[3][i].in[23] <== eq[72][i].out;
|
||||
multi_or[3][i].in[24] <== eq[73][i].out;
|
||||
multi_or[3][i].in[25] <== eq[74][i].out;
|
||||
multi_or[3][i].in[26] <== eq[75][i].out;
|
||||
and[9][i].b <== multi_or[3][i].out;
|
||||
lt[10][i] = LessThan(8);
|
||||
lt[10][i].in[0] <== 64;
|
||||
lt[10][i].in[1] <== in[i];
|
||||
lt[11][i] = LessThan(8);
|
||||
lt[11][i].in[0] <== in[i];
|
||||
lt[11][i].in[1] <== 127;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== lt[10][i].out;
|
||||
and[10][i].b <== lt[11][i].out;
|
||||
eq[76][i] = IsEqual();
|
||||
eq[76][i].in[0] <== in[i];
|
||||
eq[76][i].in[1] <== 9;
|
||||
eq[77][i] = IsEqual();
|
||||
eq[77][i].in[0] <== in[i];
|
||||
eq[77][i].in[1] <== 10;
|
||||
eq[78][i] = IsEqual();
|
||||
eq[78][i].in[0] <== in[i];
|
||||
eq[78][i].in[1] <== 13;
|
||||
eq[79][i] = IsEqual();
|
||||
eq[79][i].in[0] <== in[i];
|
||||
eq[79][i].in[1] <== 32;
|
||||
eq[80][i] = IsEqual();
|
||||
eq[80][i].in[0] <== in[i];
|
||||
eq[80][i].in[1] <== 33;
|
||||
eq[81][i] = IsEqual();
|
||||
eq[81][i].in[0] <== in[i];
|
||||
eq[81][i].in[1] <== 34;
|
||||
eq[82][i] = IsEqual();
|
||||
eq[82][i].in[0] <== in[i];
|
||||
eq[82][i].in[1] <== 35;
|
||||
eq[83][i] = IsEqual();
|
||||
eq[83][i].in[0] <== in[i];
|
||||
eq[83][i].in[1] <== 36;
|
||||
eq[84][i] = IsEqual();
|
||||
eq[84][i].in[0] <== in[i];
|
||||
eq[84][i].in[1] <== 37;
|
||||
eq[85][i] = IsEqual();
|
||||
eq[85][i].in[0] <== in[i];
|
||||
eq[85][i].in[1] <== 38;
|
||||
eq[86][i] = IsEqual();
|
||||
eq[86][i].in[0] <== in[i];
|
||||
eq[86][i].in[1] <== 39;
|
||||
eq[87][i] = IsEqual();
|
||||
eq[87][i].in[0] <== in[i];
|
||||
eq[87][i].in[1] <== 40;
|
||||
eq[88][i] = IsEqual();
|
||||
eq[88][i].in[0] <== in[i];
|
||||
eq[88][i].in[1] <== 41;
|
||||
eq[89][i] = IsEqual();
|
||||
eq[89][i].in[0] <== in[i];
|
||||
eq[89][i].in[1] <== 42;
|
||||
eq[90][i] = IsEqual();
|
||||
eq[90][i].in[0] <== in[i];
|
||||
eq[90][i].in[1] <== 43;
|
||||
eq[91][i] = IsEqual();
|
||||
eq[91][i].in[0] <== in[i];
|
||||
eq[91][i].in[1] <== 44;
|
||||
eq[92][i] = IsEqual();
|
||||
eq[92][i].in[0] <== in[i];
|
||||
eq[92][i].in[1] <== 45;
|
||||
eq[93][i] = IsEqual();
|
||||
eq[93][i].in[0] <== in[i];
|
||||
eq[93][i].in[1] <== 46;
|
||||
eq[94][i] = IsEqual();
|
||||
eq[94][i].in[0] <== in[i];
|
||||
eq[94][i].in[1] <== 47;
|
||||
eq[95][i] = IsEqual();
|
||||
eq[95][i].in[0] <== in[i];
|
||||
eq[95][i].in[1] <== 58;
|
||||
eq[96][i] = IsEqual();
|
||||
eq[96][i].in[0] <== in[i];
|
||||
eq[96][i].in[1] <== 60;
|
||||
eq[97][i] = IsEqual();
|
||||
eq[97][i].in[0] <== in[i];
|
||||
eq[97][i].in[1] <== 61;
|
||||
eq[98][i] = IsEqual();
|
||||
eq[98][i].in[0] <== in[i];
|
||||
eq[98][i].in[1] <== 62;
|
||||
eq[99][i] = IsEqual();
|
||||
eq[99][i].in[0] <== in[i];
|
||||
eq[99][i].in[1] <== 63;
|
||||
eq[100][i] = IsEqual();
|
||||
eq[100][i].in[0] <== in[i];
|
||||
eq[100][i].in[1] <== 64;
|
||||
and[11][i] = AND();
|
||||
and[11][i].a <== states[i][16];
|
||||
multi_or[4][i] = MultiOR(26);
|
||||
multi_or[4][i].in[0] <== and[10][i].out;
|
||||
multi_or[4][i].in[1] <== eq[76][i].out;
|
||||
multi_or[4][i].in[2] <== eq[77][i].out;
|
||||
multi_or[4][i].in[3] <== eq[78][i].out;
|
||||
multi_or[4][i].in[4] <== eq[79][i].out;
|
||||
multi_or[4][i].in[5] <== eq[80][i].out;
|
||||
multi_or[4][i].in[6] <== eq[81][i].out;
|
||||
multi_or[4][i].in[7] <== eq[82][i].out;
|
||||
multi_or[4][i].in[8] <== eq[83][i].out;
|
||||
multi_or[4][i].in[9] <== eq[84][i].out;
|
||||
multi_or[4][i].in[10] <== eq[85][i].out;
|
||||
multi_or[4][i].in[11] <== eq[86][i].out;
|
||||
multi_or[4][i].in[12] <== eq[87][i].out;
|
||||
multi_or[4][i].in[13] <== eq[88][i].out;
|
||||
multi_or[4][i].in[14] <== eq[89][i].out;
|
||||
multi_or[4][i].in[15] <== eq[90][i].out;
|
||||
multi_or[4][i].in[16] <== eq[91][i].out;
|
||||
multi_or[4][i].in[17] <== eq[92][i].out;
|
||||
multi_or[4][i].in[18] <== eq[93][i].out;
|
||||
multi_or[4][i].in[19] <== eq[94][i].out;
|
||||
multi_or[4][i].in[20] <== eq[95][i].out;
|
||||
multi_or[4][i].in[21] <== eq[96][i].out;
|
||||
multi_or[4][i].in[22] <== eq[97][i].out;
|
||||
multi_or[4][i].in[23] <== eq[98][i].out;
|
||||
multi_or[4][i].in[24] <== eq[99][i].out;
|
||||
multi_or[4][i].in[25] <== eq[100][i].out;
|
||||
and[11][i].b <== multi_or[4][i].out;
|
||||
lt[12][i] = LessThan(8);
|
||||
lt[12][i].in[0] <== 64;
|
||||
lt[12][i].in[1] <== in[i];
|
||||
lt[13][i] = LessThan(8);
|
||||
lt[13][i].in[0] <== in[i];
|
||||
lt[13][i].in[1] <== 127;
|
||||
and[12][i] = AND();
|
||||
and[12][i].a <== lt[12][i].out;
|
||||
and[12][i].b <== lt[13][i].out;
|
||||
eq[101][i] = IsEqual();
|
||||
eq[101][i].in[0] <== in[i];
|
||||
eq[101][i].in[1] <== 9;
|
||||
eq[102][i] = IsEqual();
|
||||
eq[102][i].in[0] <== in[i];
|
||||
eq[102][i].in[1] <== 10;
|
||||
eq[103][i] = IsEqual();
|
||||
eq[103][i].in[0] <== in[i];
|
||||
eq[103][i].in[1] <== 13;
|
||||
eq[104][i] = IsEqual();
|
||||
eq[104][i].in[0] <== in[i];
|
||||
eq[104][i].in[1] <== 32;
|
||||
eq[105][i] = IsEqual();
|
||||
eq[105][i].in[0] <== in[i];
|
||||
eq[105][i].in[1] <== 33;
|
||||
eq[106][i] = IsEqual();
|
||||
eq[106][i].in[0] <== in[i];
|
||||
eq[106][i].in[1] <== 34;
|
||||
eq[107][i] = IsEqual();
|
||||
eq[107][i].in[0] <== in[i];
|
||||
eq[107][i].in[1] <== 35;
|
||||
eq[108][i] = IsEqual();
|
||||
eq[108][i].in[0] <== in[i];
|
||||
eq[108][i].in[1] <== 36;
|
||||
eq[109][i] = IsEqual();
|
||||
eq[109][i].in[0] <== in[i];
|
||||
eq[109][i].in[1] <== 37;
|
||||
eq[110][i] = IsEqual();
|
||||
eq[110][i].in[0] <== in[i];
|
||||
eq[110][i].in[1] <== 38;
|
||||
eq[111][i] = IsEqual();
|
||||
eq[111][i].in[0] <== in[i];
|
||||
eq[111][i].in[1] <== 39;
|
||||
eq[112][i] = IsEqual();
|
||||
eq[112][i].in[0] <== in[i];
|
||||
eq[112][i].in[1] <== 40;
|
||||
eq[113][i] = IsEqual();
|
||||
eq[113][i].in[0] <== in[i];
|
||||
eq[113][i].in[1] <== 41;
|
||||
eq[114][i] = IsEqual();
|
||||
eq[114][i].in[0] <== in[i];
|
||||
eq[114][i].in[1] <== 42;
|
||||
eq[115][i] = IsEqual();
|
||||
eq[115][i].in[0] <== in[i];
|
||||
eq[115][i].in[1] <== 43;
|
||||
eq[116][i] = IsEqual();
|
||||
eq[116][i].in[0] <== in[i];
|
||||
eq[116][i].in[1] <== 44;
|
||||
eq[117][i] = IsEqual();
|
||||
eq[117][i].in[0] <== in[i];
|
||||
eq[117][i].in[1] <== 45;
|
||||
eq[118][i] = IsEqual();
|
||||
eq[118][i].in[0] <== in[i];
|
||||
eq[118][i].in[1] <== 46;
|
||||
eq[119][i] = IsEqual();
|
||||
eq[119][i].in[0] <== in[i];
|
||||
eq[119][i].in[1] <== 47;
|
||||
eq[120][i] = IsEqual();
|
||||
eq[120][i].in[0] <== in[i];
|
||||
eq[120][i].in[1] <== 58;
|
||||
eq[121][i] = IsEqual();
|
||||
eq[121][i].in[0] <== in[i];
|
||||
eq[121][i].in[1] <== 60;
|
||||
eq[122][i] = IsEqual();
|
||||
eq[122][i].in[0] <== in[i];
|
||||
eq[122][i].in[1] <== 61;
|
||||
eq[123][i] = IsEqual();
|
||||
eq[123][i].in[0] <== in[i];
|
||||
eq[123][i].in[1] <== 62;
|
||||
eq[124][i] = IsEqual();
|
||||
eq[124][i].in[0] <== in[i];
|
||||
eq[124][i].in[1] <== 63;
|
||||
eq[125][i] = IsEqual();
|
||||
eq[125][i].in[0] <== in[i];
|
||||
eq[125][i].in[1] <== 64;
|
||||
and[13][i] = AND();
|
||||
and[13][i].a <== states[i][21];
|
||||
multi_or[5][i] = MultiOR(26);
|
||||
multi_or[5][i].in[0] <== and[12][i].out;
|
||||
multi_or[5][i].in[1] <== eq[101][i].out;
|
||||
multi_or[5][i].in[2] <== eq[102][i].out;
|
||||
multi_or[5][i].in[3] <== eq[103][i].out;
|
||||
multi_or[5][i].in[4] <== eq[104][i].out;
|
||||
multi_or[5][i].in[5] <== eq[105][i].out;
|
||||
multi_or[5][i].in[6] <== eq[106][i].out;
|
||||
multi_or[5][i].in[7] <== eq[107][i].out;
|
||||
multi_or[5][i].in[8] <== eq[108][i].out;
|
||||
multi_or[5][i].in[9] <== eq[109][i].out;
|
||||
multi_or[5][i].in[10] <== eq[110][i].out;
|
||||
multi_or[5][i].in[11] <== eq[111][i].out;
|
||||
multi_or[5][i].in[12] <== eq[112][i].out;
|
||||
multi_or[5][i].in[13] <== eq[113][i].out;
|
||||
multi_or[5][i].in[14] <== eq[114][i].out;
|
||||
multi_or[5][i].in[15] <== eq[115][i].out;
|
||||
multi_or[5][i].in[16] <== eq[116][i].out;
|
||||
multi_or[5][i].in[17] <== eq[117][i].out;
|
||||
multi_or[5][i].in[18] <== eq[118][i].out;
|
||||
multi_or[5][i].in[19] <== eq[119][i].out;
|
||||
multi_or[5][i].in[20] <== eq[120][i].out;
|
||||
multi_or[5][i].in[21] <== eq[121][i].out;
|
||||
multi_or[5][i].in[22] <== eq[122][i].out;
|
||||
multi_or[5][i].in[23] <== eq[123][i].out;
|
||||
multi_or[5][i].in[24] <== eq[124][i].out;
|
||||
multi_or[5][i].in[25] <== eq[125][i].out;
|
||||
and[13][i].b <== multi_or[5][i].out;
|
||||
multi_or[6][i] = MultiOR(4);
|
||||
multi_or[6][i].in[0] <== and[6][i].out;
|
||||
multi_or[6][i].in[1] <== and[9][i].out;
|
||||
multi_or[6][i].in[2] <== and[11][i].out;
|
||||
multi_or[6][i].in[3] <== and[13][i].out;
|
||||
states[i+1][3] <== multi_or[6][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
eq[126][i] = IsEqual();
|
||||
eq[126][i].in[0] <== in[i];
|
||||
eq[126][i].in[1] <== 100;
|
||||
and[14][i] = AND();
|
||||
and[14][i].a <== states[i][0];
|
||||
and[14][i].b <== eq[126][i].out;
|
||||
states[i+1][4] <== and[14][i].out;
|
||||
state_changed[i].in[3] <== states[i+1][4];
|
||||
eq[127][i] = IsEqual();
|
||||
eq[127][i].in[0] <== in[i];
|
||||
eq[127][i].in[1] <== 107;
|
||||
and[15][i] = AND();
|
||||
and[15][i].a <== states[i][4];
|
||||
and[15][i].b <== eq[127][i].out;
|
||||
states[i+1][5] <== and[15][i].out;
|
||||
state_changed[i].in[4] <== states[i+1][5];
|
||||
eq[128][i] = IsEqual();
|
||||
eq[128][i].in[0] <== in[i];
|
||||
eq[128][i].in[1] <== 105;
|
||||
and[16][i] = AND();
|
||||
and[16][i].a <== states[i][5];
|
||||
and[16][i].b <== eq[128][i].out;
|
||||
states[i+1][6] <== and[16][i].out;
|
||||
state_changed[i].in[5] <== states[i+1][6];
|
||||
eq[129][i] = IsEqual();
|
||||
eq[129][i].in[0] <== in[i];
|
||||
eq[129][i].in[1] <== 109;
|
||||
and[17][i] = AND();
|
||||
and[17][i].a <== states[i][6];
|
||||
and[17][i].b <== eq[129][i].out;
|
||||
states[i+1][7] <== and[17][i].out;
|
||||
state_changed[i].in[6] <== states[i+1][7];
|
||||
eq[130][i] = IsEqual();
|
||||
eq[130][i].in[0] <== in[i];
|
||||
eq[130][i].in[1] <== 45;
|
||||
and[18][i] = AND();
|
||||
and[18][i].a <== states[i][7];
|
||||
and[18][i].b <== eq[130][i].out;
|
||||
states[i+1][8] <== and[18][i].out;
|
||||
state_changed[i].in[7] <== states[i+1][8];
|
||||
eq[131][i] = IsEqual();
|
||||
eq[131][i].in[0] <== in[i];
|
||||
eq[131][i].in[1] <== 59;
|
||||
and[19][i] = AND();
|
||||
and[19][i].a <== states[i][3];
|
||||
and[19][i].b <== eq[131][i].out;
|
||||
states[i+1][9] <== and[19][i].out;
|
||||
state_changed[i].in[8] <== states[i+1][9];
|
||||
eq[132][i] = IsEqual();
|
||||
eq[132][i].in[0] <== in[i];
|
||||
eq[132][i].in[1] <== 115;
|
||||
and[20][i] = AND();
|
||||
and[20][i].a <== states[i][8];
|
||||
and[20][i].b <== eq[132][i].out;
|
||||
states[i+1][10] <== and[20][i].out;
|
||||
state_changed[i].in[9] <== states[i+1][10];
|
||||
eq[133][i] = IsEqual();
|
||||
eq[133][i].in[0] <== in[i];
|
||||
eq[133][i].in[1] <== 105;
|
||||
and[21][i] = AND();
|
||||
and[21][i].a <== states[i][10];
|
||||
and[21][i].b <== eq[133][i].out;
|
||||
states[i+1][11] <== and[21][i].out;
|
||||
state_changed[i].in[10] <== states[i+1][11];
|
||||
eq[134][i] = IsEqual();
|
||||
eq[134][i].in[0] <== in[i];
|
||||
eq[134][i].in[1] <== 103;
|
||||
and[22][i] = AND();
|
||||
and[22][i].a <== states[i][11];
|
||||
and[22][i].b <== eq[134][i].out;
|
||||
states[i+1][12] <== and[22][i].out;
|
||||
state_changed[i].in[11] <== states[i+1][12];
|
||||
eq[135][i] = IsEqual();
|
||||
eq[135][i].in[0] <== in[i];
|
||||
eq[135][i].in[1] <== 32;
|
||||
and[23][i] = AND();
|
||||
and[23][i].a <== states[i][9];
|
||||
and[23][i].b <== eq[135][i].out;
|
||||
eq[136][i] = IsEqual();
|
||||
eq[136][i].in[0] <== in[i];
|
||||
eq[136][i].in[1] <== 32;
|
||||
and[24][i] = AND();
|
||||
and[24][i].a <== states[i][24];
|
||||
and[24][i].b <== eq[136][i].out;
|
||||
multi_or[7][i] = MultiOR(2);
|
||||
multi_or[7][i].in[0] <== and[23][i].out;
|
||||
multi_or[7][i].in[1] <== and[24][i].out;
|
||||
states[i+1][13] <== multi_or[7][i].out;
|
||||
state_changed[i].in[12] <== states[i+1][13];
|
||||
eq[137][i] = IsEqual();
|
||||
eq[137][i].in[0] <== in[i];
|
||||
eq[137][i].in[1] <== 110;
|
||||
and[25][i] = AND();
|
||||
and[25][i].a <== states[i][12];
|
||||
and[25][i].b <== eq[137][i].out;
|
||||
states[i+1][14] <== and[25][i].out;
|
||||
state_changed[i].in[13] <== states[i+1][14];
|
||||
eq[138][i] = IsEqual();
|
||||
eq[138][i].in[0] <== in[i];
|
||||
eq[138][i].in[1] <== 116;
|
||||
and[26][i] = AND();
|
||||
and[26][i].a <== states[i][13];
|
||||
and[26][i].b <== eq[138][i].out;
|
||||
states[i+1][15] <== and[26][i].out;
|
||||
state_changed[i].in[14] <== states[i+1][15];
|
||||
eq[139][i] = IsEqual();
|
||||
eq[139][i].in[0] <== in[i];
|
||||
eq[139][i].in[1] <== 61;
|
||||
and[27][i] = AND();
|
||||
and[27][i].a <== states[i][15];
|
||||
and[27][i].b <== eq[139][i].out;
|
||||
states[i+1][16] <== and[27][i].out;
|
||||
state_changed[i].in[15] <== states[i+1][16];
|
||||
eq[140][i] = IsEqual();
|
||||
eq[140][i].in[0] <== in[i];
|
||||
eq[140][i].in[1] <== 97;
|
||||
and[28][i] = AND();
|
||||
and[28][i].a <== states[i][14];
|
||||
and[28][i].b <== eq[140][i].out;
|
||||
states[i+1][17] <== and[28][i].out;
|
||||
state_changed[i].in[16] <== states[i+1][17];
|
||||
eq[141][i] = IsEqual();
|
||||
eq[141][i].in[0] <== in[i];
|
||||
eq[141][i].in[1] <== 116;
|
||||
and[29][i] = AND();
|
||||
and[29][i].a <== states[i][17];
|
||||
and[29][i].b <== eq[141][i].out;
|
||||
states[i+1][18] <== and[29][i].out;
|
||||
state_changed[i].in[17] <== states[i+1][18];
|
||||
eq[142][i] = IsEqual();
|
||||
eq[142][i].in[0] <== in[i];
|
||||
eq[142][i].in[1] <== 117;
|
||||
and[30][i] = AND();
|
||||
and[30][i].a <== states[i][18];
|
||||
and[30][i].b <== eq[142][i].out;
|
||||
states[i+1][19] <== and[30][i].out;
|
||||
state_changed[i].in[18] <== states[i+1][19];
|
||||
eq[143][i] = IsEqual();
|
||||
eq[143][i].in[0] <== in[i];
|
||||
eq[143][i].in[1] <== 114;
|
||||
and[31][i] = AND();
|
||||
and[31][i].a <== states[i][19];
|
||||
and[31][i].b <== eq[143][i].out;
|
||||
states[i+1][20] <== and[31][i].out;
|
||||
state_changed[i].in[19] <== states[i+1][20];
|
||||
lt[14][i] = LessThan(8);
|
||||
lt[14][i].in[0] <== 47;
|
||||
lt[14][i].in[1] <== in[i];
|
||||
lt[15][i] = LessThan(8);
|
||||
lt[15][i].in[0] <== in[i];
|
||||
lt[15][i].in[1] <== 58;
|
||||
and[32][i] = AND();
|
||||
and[32][i].a <== lt[14][i].out;
|
||||
and[32][i].b <== lt[15][i].out;
|
||||
and[33][i] = AND();
|
||||
and[33][i].a <== states[i][16];
|
||||
and[33][i].b <== and[32][i].out;
|
||||
lt[16][i] = LessThan(8);
|
||||
lt[16][i].in[0] <== 47;
|
||||
lt[16][i].in[1] <== in[i];
|
||||
lt[17][i] = LessThan(8);
|
||||
lt[17][i].in[0] <== in[i];
|
||||
lt[17][i].in[1] <== 58;
|
||||
and[34][i] = AND();
|
||||
and[34][i].a <== lt[16][i].out;
|
||||
and[34][i].b <== lt[17][i].out;
|
||||
and[35][i] = AND();
|
||||
and[35][i].a <== states[i][21];
|
||||
and[35][i].b <== and[34][i].out;
|
||||
multi_or[8][i] = MultiOR(2);
|
||||
multi_or[8][i].in[0] <== and[33][i].out;
|
||||
multi_or[8][i].in[1] <== and[35][i].out;
|
||||
states[i+1][21] <== multi_or[8][i].out;
|
||||
state_changed[i].in[20] <== states[i+1][21];
|
||||
eq[144][i] = IsEqual();
|
||||
eq[144][i].in[0] <== in[i];
|
||||
eq[144][i].in[1] <== 101;
|
||||
and[36][i] = AND();
|
||||
and[36][i].a <== states[i][20];
|
||||
and[36][i].b <== eq[144][i].out;
|
||||
states[i+1][22] <== and[36][i].out;
|
||||
state_changed[i].in[21] <== states[i+1][22];
|
||||
eq[145][i] = IsEqual();
|
||||
eq[145][i].in[0] <== in[i];
|
||||
eq[145][i].in[1] <== 58;
|
||||
and[37][i] = AND();
|
||||
and[37][i].a <== states[i][22];
|
||||
and[37][i].b <== eq[145][i].out;
|
||||
states[i+1][23] <== and[37][i].out;
|
||||
state_changed[i].in[22] <== states[i+1][23];
|
||||
eq[146][i] = IsEqual();
|
||||
eq[146][i].in[0] <== in[i];
|
||||
eq[146][i].in[1] <== 59;
|
||||
and[38][i] = AND();
|
||||
and[38][i].a <== states[i][21];
|
||||
and[38][i].b <== eq[146][i].out;
|
||||
states[i+1][24] <== and[38][i].out;
|
||||
state_changed[i].in[23] <== states[i+1][24];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][24];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][24] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][3];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][21] * states[i+2][21];
|
||||
is_substr0[i][2] <== is_substr0[i][1] + states[i+1][16] * states[i+2][21];
|
||||
is_reveal0[i] <== is_substr0[i][2] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
}
|
||||
48
packages/circom/circuits/regex_helpers.circom
Normal file
48
packages/circom/circuits/regex_helpers.circom
Normal file
@@ -0,0 +1,48 @@
|
||||
pragma circom 2.0.3;
|
||||
|
||||
include "circomlib/circuits/comparators.circom";
|
||||
include "circomlib/circuits/gates.circom";
|
||||
|
||||
// template MultiOROld(n) {
|
||||
// signal input in[n];
|
||||
// signal output out;
|
||||
// component or1;
|
||||
// component or2;
|
||||
// component ors[2];
|
||||
// if (n==1) {
|
||||
// out <== in[0];
|
||||
// } else if (n==2) {
|
||||
// or1 = OR();
|
||||
// or1.a <== in[0];
|
||||
// or1.b <== in[1];
|
||||
// out <== or1.out;
|
||||
// } else {
|
||||
// or2 = OR();
|
||||
// var n1 = n\2;
|
||||
// var n2 = n-n\2;
|
||||
// ors[0] = MultiOR(n1);
|
||||
// ors[1] = MultiOR(n2);
|
||||
// var i;
|
||||
// for (i=0; i<n1; i++) ors[0].in[i] <== in[i];
|
||||
// for (i=0; i<n2; i++) ors[1].in[i] <== in[n1+i];
|
||||
// or2.a <== ors[0].out;
|
||||
// or2.b <== ors[1].out;
|
||||
// out <== or2.out;
|
||||
// }
|
||||
// }
|
||||
|
||||
template MultiOR(n) {
|
||||
signal input in[n];
|
||||
signal output out;
|
||||
|
||||
signal sums[n];
|
||||
sums[0] <== in[0];
|
||||
for (var i = 1; i < n; i++) {
|
||||
sums[i] <== sums[i-1] + in[i];
|
||||
}
|
||||
|
||||
component is_zero = IsZero();
|
||||
is_zero.in <== sums[n-1];
|
||||
out <== 1 - is_zero.out;
|
||||
}
|
||||
|
||||
35
packages/circom/package.json
Normal file
35
packages/circom/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "zk-regex-circom",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": "^11.0.0",
|
||||
"snarkjs": "^0.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.4",
|
||||
"chai": "^4.3.7",
|
||||
"circom_tester": "^0.0.19",
|
||||
"circomlib": "^2.0.5",
|
||||
"circomlibjs": "^0.1.2",
|
||||
"ffjavascript": "^0.2.59",
|
||||
"jest": "^29.5.0",
|
||||
"mocha": "^10.2.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^4.8.3"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env"
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
[
|
||||
"jest"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
180
packages/circom/tests/circuits/simple_regex.circom
Normal file
180
packages/circom/tests/circuits/simple_regex.circom
Normal file
@@ -0,0 +1,180 @@
|
||||
pragma circom 2.1.5;
|
||||
|
||||
include "zk-regex-circom/circuits/regex_helpers.circom";
|
||||
|
||||
template SimpleRegex(msg_bytes) {
|
||||
signal input msg[msg_bytes];
|
||||
signal output out;
|
||||
|
||||
var num_bytes = msg_bytes+1;
|
||||
signal in[num_bytes];
|
||||
in[0]<==128;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
in[i+1] <== msg[i];
|
||||
}
|
||||
|
||||
component eq[14][num_bytes];
|
||||
component and[11][num_bytes];
|
||||
component multi_or[5][num_bytes];
|
||||
signal states[num_bytes+1][10];
|
||||
component state_changed[num_bytes];
|
||||
|
||||
states[0][0] <== 1;
|
||||
for (var i = 1; i < 10; i++) {
|
||||
states[0][i] <== 0;
|
||||
}
|
||||
|
||||
for (var i = 0; i < num_bytes; i++) {
|
||||
state_changed[i] = MultiOR(9);
|
||||
eq[0][i] = IsEqual();
|
||||
eq[0][i].in[0] <== in[i];
|
||||
eq[0][i].in[1] <== 49;
|
||||
and[0][i] = AND();
|
||||
and[0][i].a <== states[i][0];
|
||||
and[0][i].b <== eq[0][i].out;
|
||||
states[i+1][1] <== and[0][i].out;
|
||||
state_changed[i].in[0] <== states[i+1][1];
|
||||
eq[1][i] = IsEqual();
|
||||
eq[1][i].in[0] <== in[i];
|
||||
eq[1][i].in[1] <== 61;
|
||||
and[1][i] = AND();
|
||||
and[1][i].a <== states[i][1];
|
||||
and[1][i].b <== eq[1][i].out;
|
||||
states[i+1][2] <== and[1][i].out;
|
||||
state_changed[i].in[1] <== states[i+1][2];
|
||||
eq[2][i] = IsEqual();
|
||||
eq[2][i].in[0] <== in[i];
|
||||
eq[2][i].in[1] <== 97;
|
||||
eq[3][i] = IsEqual();
|
||||
eq[3][i].in[0] <== in[i];
|
||||
eq[3][i].in[1] <== 98;
|
||||
and[2][i] = AND();
|
||||
and[2][i].a <== states[i][2];
|
||||
multi_or[0][i] = MultiOR(2);
|
||||
multi_or[0][i].in[0] <== eq[2][i].out;
|
||||
multi_or[0][i].in[1] <== eq[3][i].out;
|
||||
and[2][i].b <== multi_or[0][i].out;
|
||||
states[i+1][3] <== and[2][i].out;
|
||||
state_changed[i].in[2] <== states[i+1][3];
|
||||
eq[4][i] = IsEqual();
|
||||
eq[4][i].in[0] <== in[i];
|
||||
eq[4][i].in[1] <== 32;
|
||||
and[3][i] = AND();
|
||||
and[3][i].a <== states[i][3];
|
||||
and[3][i].b <== eq[4][i].out;
|
||||
states[i+1][4] <== and[3][i].out;
|
||||
state_changed[i].in[3] <== states[i+1][4];
|
||||
eq[5][i] = IsEqual();
|
||||
eq[5][i].in[0] <== in[i];
|
||||
eq[5][i].in[1] <== 50;
|
||||
and[4][i] = AND();
|
||||
and[4][i].a <== states[i][4];
|
||||
and[4][i].b <== eq[5][i].out;
|
||||
eq[6][i] = IsEqual();
|
||||
eq[6][i].in[0] <== in[i];
|
||||
eq[6][i].in[1] <== 50;
|
||||
and[5][i] = AND();
|
||||
and[5][i].a <== states[i][8];
|
||||
and[5][i].b <== eq[6][i].out;
|
||||
multi_or[1][i] = MultiOR(2);
|
||||
multi_or[1][i].in[0] <== and[4][i].out;
|
||||
multi_or[1][i].in[1] <== and[5][i].out;
|
||||
states[i+1][5] <== multi_or[1][i].out;
|
||||
state_changed[i].in[4] <== states[i+1][5];
|
||||
eq[7][i] = IsEqual();
|
||||
eq[7][i].in[0] <== in[i];
|
||||
eq[7][i].in[1] <== 61;
|
||||
and[6][i] = AND();
|
||||
and[6][i].a <== states[i][5];
|
||||
and[6][i].b <== eq[7][i].out;
|
||||
states[i+1][6] <== and[6][i].out;
|
||||
state_changed[i].in[5] <== states[i+1][6];
|
||||
eq[8][i] = IsEqual();
|
||||
eq[8][i].in[0] <== in[i];
|
||||
eq[8][i].in[1] <== 98;
|
||||
eq[9][i] = IsEqual();
|
||||
eq[9][i].in[0] <== in[i];
|
||||
eq[9][i].in[1] <== 99;
|
||||
and[7][i] = AND();
|
||||
and[7][i].a <== states[i][6];
|
||||
multi_or[2][i] = MultiOR(2);
|
||||
multi_or[2][i].in[0] <== eq[8][i].out;
|
||||
multi_or[2][i].in[1] <== eq[9][i].out;
|
||||
and[7][i].b <== multi_or[2][i].out;
|
||||
eq[10][i] = IsEqual();
|
||||
eq[10][i].in[0] <== in[i];
|
||||
eq[10][i].in[1] <== 98;
|
||||
eq[11][i] = IsEqual();
|
||||
eq[11][i].in[0] <== in[i];
|
||||
eq[11][i].in[1] <== 99;
|
||||
and[8][i] = AND();
|
||||
and[8][i].a <== states[i][7];
|
||||
multi_or[3][i] = MultiOR(2);
|
||||
multi_or[3][i].in[0] <== eq[10][i].out;
|
||||
multi_or[3][i].in[1] <== eq[11][i].out;
|
||||
and[8][i].b <== multi_or[3][i].out;
|
||||
multi_or[4][i] = MultiOR(2);
|
||||
multi_or[4][i].in[0] <== and[7][i].out;
|
||||
multi_or[4][i].in[1] <== and[8][i].out;
|
||||
states[i+1][7] <== multi_or[4][i].out;
|
||||
state_changed[i].in[6] <== states[i+1][7];
|
||||
eq[12][i] = IsEqual();
|
||||
eq[12][i].in[0] <== in[i];
|
||||
eq[12][i].in[1] <== 32;
|
||||
and[9][i] = AND();
|
||||
and[9][i].a <== states[i][7];
|
||||
and[9][i].b <== eq[12][i].out;
|
||||
states[i+1][8] <== and[9][i].out;
|
||||
state_changed[i].in[7] <== states[i+1][8];
|
||||
eq[13][i] = IsEqual();
|
||||
eq[13][i].in[0] <== in[i];
|
||||
eq[13][i].in[1] <== 100;
|
||||
and[10][i] = AND();
|
||||
and[10][i].a <== states[i][8];
|
||||
and[10][i].b <== eq[13][i].out;
|
||||
states[i+1][9] <== and[10][i].out;
|
||||
state_changed[i].in[8] <== states[i+1][9];
|
||||
states[i+1][0] <== 1 - state_changed[i].out;
|
||||
}
|
||||
|
||||
component final_state_result = MultiOR(num_bytes+1);
|
||||
for (var i = 0; i <= num_bytes; i++) {
|
||||
final_state_result.in[i] <== states[i][9];
|
||||
}
|
||||
out <== final_state_result.out;
|
||||
|
||||
signal is_consecutive[msg_bytes+1][2];
|
||||
is_consecutive[msg_bytes][1] <== 1;
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][9] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];
|
||||
is_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];
|
||||
}
|
||||
signal is_substr0[msg_bytes][2];
|
||||
signal is_reveal0[msg_bytes];
|
||||
signal output reveal0[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr0[i][0] <== 0;
|
||||
is_substr0[i][1] <== is_substr0[i][0] + states[i+1][2] * states[i+2][3];
|
||||
is_reveal0[i] <== is_substr0[i][1] * is_consecutive[i][1];
|
||||
reveal0[i] <== in[i+1] * is_reveal0[i];
|
||||
}
|
||||
signal is_substr1[msg_bytes][3];
|
||||
signal is_reveal1[msg_bytes];
|
||||
signal output reveal1[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr1[i][0] <== 0;
|
||||
is_substr1[i][1] <== is_substr1[i][0] + states[i+1][7] * states[i+2][7];
|
||||
is_substr1[i][2] <== is_substr1[i][1] + states[i+1][6] * states[i+2][7];
|
||||
is_reveal1[i] <== is_substr1[i][2] * is_consecutive[i][1];
|
||||
reveal1[i] <== in[i+1] * is_reveal1[i];
|
||||
}
|
||||
signal is_substr2[msg_bytes][2];
|
||||
signal is_reveal2[msg_bytes];
|
||||
signal output reveal2[msg_bytes];
|
||||
for (var i = 0; i < msg_bytes; i++) {
|
||||
is_substr2[i][0] <== 0;
|
||||
is_substr2[i][1] <== is_substr2[i][0] + states[i+1][8] * states[i+2][9];
|
||||
is_reveal2[i] <== is_substr2[i][1] * is_consecutive[i][1];
|
||||
reveal2[i] <== in[i+1] * is_reveal2[i];
|
||||
}
|
||||
}
|
||||
26
packages/circom/tests/circuits/simple_regex_substrs.json
Normal file
26
packages/circom/tests/circuits/simple_regex_substrs.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"transitions": [
|
||||
[
|
||||
[
|
||||
2,
|
||||
3
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
6,
|
||||
7
|
||||
],
|
||||
[
|
||||
7,
|
||||
7
|
||||
]
|
||||
],
|
||||
[
|
||||
[
|
||||
8,
|
||||
9
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
include "../../circuits/common/email_addr_regex.circom";
|
||||
|
||||
component main = EmailAddrRegex(256);
|
||||
@@ -0,0 +1,3 @@
|
||||
include "../../circuits/common/email_domain_regex.circom";
|
||||
|
||||
component main = EmailDomainRegex(256);
|
||||
@@ -0,0 +1,3 @@
|
||||
include "../../circuits/common/from_addr_regex.circom";
|
||||
|
||||
component main = FromAddrRegex(1024);
|
||||
3
packages/circom/tests/circuits/test_simple_regex.circom
Normal file
3
packages/circom/tests/circuits/test_simple_regex.circom
Normal file
@@ -0,0 +1,3 @@
|
||||
include "./simple_regex.circom";
|
||||
// 1=(a|b) (2=(b|c)+ )+d
|
||||
component main = SimpleRegex(64);
|
||||
@@ -0,0 +1,3 @@
|
||||
include "../../circuits/common/subject_all_regex.circom";
|
||||
|
||||
component main = SubjectAllRegex(256);
|
||||
@@ -0,0 +1,3 @@
|
||||
include "../../circuits/common/timestamp_regex.circom";
|
||||
|
||||
component main = TimestampRegex(1024);
|
||||
49
packages/circom/tests/email_addr.test.ts
Normal file
49
packages/circom/tests/email_addr.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("Email Address Regex", () => {
|
||||
it("only an email address", async () => {
|
||||
const emailAddr = "suegamisora@gmail.com";
|
||||
const paddedEmailAddr = apis.padString(emailAddr, 256);
|
||||
const circuitInputs = {
|
||||
msg: paddedEmailAddr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_email_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
for (let idx = 0; idx < emailAddr.length; ++idx) {
|
||||
expect(BigInt(paddedEmailAddr[idx])).toEqual(witness[2 + idx]);
|
||||
}
|
||||
});
|
||||
|
||||
it("with a prefix", async () => {
|
||||
const prefix = "subject:";
|
||||
const emailAddr = "suegamisora@gmail.com";
|
||||
const string = prefix + emailAddr;
|
||||
console.log(string);
|
||||
const paddedStr = apis.padString(string, 256);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_email_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(string, readFileSync(path.join(__dirname, "../circuits/common/email_addr.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < emailAddr.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
});
|
||||
35
packages/circom/tests/email_domain.test.ts
Normal file
35
packages/circom/tests/email_domain.test.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("Email Domain Regex", () => {
|
||||
it("test a regex of an email domain", async () => {
|
||||
const emailAddr = "suegamisora@gmail.com";
|
||||
const paddedEmailAddr = apis.padString(emailAddr, 256);
|
||||
const revealed = "gmail.com";
|
||||
const circuitInputs = {
|
||||
msg: paddedEmailAddr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_email_domain_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
for (let idx = 0; idx < 12; ++idx) {
|
||||
expect(0n).toEqual(witness[2 + idx]);
|
||||
}
|
||||
const prefixIdx = apis.extractSubstrIdxes(emailAddr, readFileSync(path.join(__dirname, "../circuits/common/email_domain.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedEmailAddr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
});
|
||||
90
packages/circom/tests/from_addr.test.ts
Normal file
90
packages/circom/tests/from_addr.test.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("From Addr Regex", () => {
|
||||
it("from field from beginning case 1", async () => {
|
||||
const fromStr = "from:suegamisora@gmail.com\r\n";
|
||||
const revealed = "suegamisora@gmail.com";
|
||||
const paddedStr = apis.padString(fromStr, 1024);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_from_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(fromStr, readFileSync(path.join(__dirname, "../circuits/common/from_addr.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
|
||||
it("from field from beginning case 2", async () => {
|
||||
const fromStr = "from:Sora Suegami <suegamisora@gmail.com>\r\n";
|
||||
const revealed = "suegamisora@gmail.com";
|
||||
// const prefixLen = "from:Sora Suegami <".length;
|
||||
const paddedStr = apis.padString(fromStr, 1024);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_from_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(fromStr, readFileSync(path.join(__dirname, "../circuits/common/from_addr.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
|
||||
it("from field after new line case 1", async () => {
|
||||
const fromStr = "dummy\r\nfrom:suegamisora@gmail.com\r\n";
|
||||
const revealed = "suegamisora@gmail.com";
|
||||
// const prefixLen = "dummy\r\nfrom:".length;
|
||||
const paddedStr = apis.padString(fromStr, 1024);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_from_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(fromStr, readFileSync(path.join(__dirname, "../circuits/common/from_addr.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
|
||||
it("from field after new line case 2", async () => {
|
||||
const fromStr = "dummy\r\nfrom:Sora Suegami <suegamisora@gmail.com>\r\n";
|
||||
const revealed = "suegamisora@gmail.com";
|
||||
// const prefixLen = "dummy\r\nfrom:Sora Suegami <".length;
|
||||
const paddedStr = apis.padString(fromStr, 1024);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_from_addr_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(fromStr, readFileSync(path.join(__dirname, "../circuits/common/from_addr.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
});
|
||||
84
packages/circom/tests/simple_regex.test.ts
Normal file
84
packages/circom/tests/simple_regex.test.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("Simple Regex", () => {
|
||||
it("case 1", async () => {
|
||||
const input = "1=a 2=b d";
|
||||
const paddedStr = apis.padString(input, 64);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_simple_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const revealedIdx = [[2], [6], [8]];
|
||||
for (let substr_idx = 0; substr_idx < 3; ++substr_idx) {
|
||||
for (let idx = 0; idx < 64; ++idx) {
|
||||
if (revealedIdx[substr_idx].includes(idx)) {
|
||||
expect(BigInt(paddedStr[idx])).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
} else {
|
||||
expect(0n).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("case 2", async () => {
|
||||
const input = "1=a 2=b 2=bc 2=c d";
|
||||
const paddedStr = apis.padString(input, 64);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_simple_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const revealedIdx = [[2], [6, 10, 11, 15], [17]];
|
||||
for (let substr_idx = 0; substr_idx < 3; ++substr_idx) {
|
||||
for (let idx = 0; idx < 64; ++idx) {
|
||||
if (revealedIdx[substr_idx].includes(idx)) {
|
||||
expect(BigInt(paddedStr[idx])).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
} else {
|
||||
expect(0n).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("case 3", async () => {
|
||||
const input = "1=a 2=b 2=bc 2=c da 1=a 2=cb 2=c 2=b dd";
|
||||
const paddedStr = apis.padString(input, 64);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_simple_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const revealedIdx = [[2, 22], [6, 10, 11, 15, 26, 27, 31, 35], [17, 37]];
|
||||
for (let substr_idx = 0; substr_idx < 3; ++substr_idx) {
|
||||
for (let idx = 0; idx < 64; ++idx) {
|
||||
if (revealedIdx[substr_idx].includes(idx)) {
|
||||
expect(BigInt(paddedStr[idx])).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
} else {
|
||||
expect(0n).toEqual(witness[2 + 64 * substr_idx + idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
54
packages/circom/tests/subject_all.test.ts
Normal file
54
packages/circom/tests/subject_all.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("Subject All Regex", () => {
|
||||
it("subject from beginning", async () => {
|
||||
const subjectStr = "subject:This is a test.\r\n";
|
||||
const revealed = "This is a test.";
|
||||
// const prefixLen = "subject:".length;
|
||||
const paddedStr = apis.padString(subjectStr, 256);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_subject_all_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(subjectStr, readFileSync(path.join(__dirname, "../circuits/common/subject_all.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
|
||||
it("subject after new line", async () => {
|
||||
const subjectStr = "dummy\r\nsubject:This is a test.\r\n";
|
||||
const revealed = "This is a test.";
|
||||
// const prefixLen = "dummy\r\nsubject:".length;
|
||||
const paddedStr = apis.padString(subjectStr, 256);
|
||||
console.log(paddedStr);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_subject_all_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
// console.log(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const prefixIdx = apis.extractSubstrIdxes(subjectStr, readFileSync(path.join(__dirname, "../circuits/common/subject_all.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[prefixIdx + idx])).toEqual(witness[2 + prefixIdx + idx]);
|
||||
}
|
||||
});
|
||||
});
|
||||
32
packages/circom/tests/timestamp.test.ts
Normal file
32
packages/circom/tests/timestamp.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
const ff = require('ffjavascript');
|
||||
const stringifyBigInts = ff.utils.stringifyBigInts;
|
||||
const circom_tester = require("circom_tester");
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
import * as path from "path";
|
||||
import { readFileSync } from "fs";
|
||||
const p = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
||||
const field = new ff.F1Field(p);
|
||||
const apis = require("../../apis");
|
||||
const option = {
|
||||
include: path.join(__dirname, "../../../node_modules")
|
||||
};
|
||||
|
||||
jest.setTimeout(120000);
|
||||
describe("Timestamp Regex", () => {
|
||||
it("timestamp in the header", async () => {
|
||||
const signatureField = `dkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1694989812; x=1695594612; dara=google.com; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=BWETwQ9JDReS4GyR2v2TTR8Bpzj9ayumsWQJ3q7vehs=; b=`;
|
||||
const revealed = "1694989812";
|
||||
const paddedStr = apis.padString(signatureField, 1024);
|
||||
const circuitInputs = {
|
||||
msg: paddedStr,
|
||||
};
|
||||
const circuit = await wasm_tester(path.join(__dirname, "./circuits/test_timestamp_regex.circom"), option);
|
||||
const witness = await circuit.calculateWitness(circuitInputs);
|
||||
await circuit.checkConstraints(witness);
|
||||
expect(1n).toEqual(witness[1]);
|
||||
const timestampIdx = apis.extractSubstrIdxes(signatureField, readFileSync(path.join(__dirname, "../circuits/common/timestamp.json"), "utf8"))[0][0];
|
||||
for (let idx = 0; idx < revealed.length; ++idx) {
|
||||
expect(BigInt(paddedStr[timestampIdx + idx])).toEqual(witness[2 + timestampIdx + idx]);
|
||||
}
|
||||
});
|
||||
});
|
||||
38
packages/compiler/Cargo.toml
Normal file
38
packages/compiler/Cargo.toml
Normal file
@@ -0,0 +1,38 @@
|
||||
[package]
|
||||
name = "zk-regex-compiler"
|
||||
version = "0.1.0"
|
||||
authors = ["Sora Suegami"]
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
# exclude = ["index.node"]
|
||||
|
||||
[[bin]]
|
||||
name = "zk-regex"
|
||||
path = "src/bin/compiler.rs"
|
||||
|
||||
[lib]
|
||||
crate-type = ["rlib", "cdylib"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tabbycat = { version = "0.1", features = ["attributes"], optional = true }
|
||||
fancy-regex = "0.11.0"
|
||||
petgraph = "0.6.3"
|
||||
graph-cycles = "0.1.0"
|
||||
thiserror = "1.0.40"
|
||||
serde_json = "1.0.95"
|
||||
serde = { version = "1.0.159", features = ["derive"] }
|
||||
js-sandbox = { version = "0.2.0-rc.1", git = "https://github.com/Bromeon/js-sandbox.git", rev = "cd256ef" }
|
||||
itertools = "0.10.3"
|
||||
clap = { version = "=4.2.1", features = ["derive"] }
|
||||
|
||||
[dependencies.neon]
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
features = ["napi-6"]
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
default = ["node"]
|
||||
node = ["neon"]
|
||||
119
packages/compiler/README.md
Normal file
119
packages/compiler/README.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# zk-regex-apis
|
||||
|
||||
This project was bootstrapped by [create-neon](https://www.npmjs.com/package/create-neon).
|
||||
|
||||
## Installing zk-regex-apis
|
||||
|
||||
Installing zk-regex-apis requires a [supported version of Node and Rust](https://github.com/neon-bindings/neon#platform-support).
|
||||
|
||||
You can install the project with npm. In the project directory, run:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
```
|
||||
|
||||
This fully installs the project, including installing any dependencies and running the build.
|
||||
|
||||
## Building zk-regex-apis
|
||||
|
||||
If you have already installed the project and only want to run the build, run:
|
||||
|
||||
```sh
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
This command uses the [cargo-cp-artifact](https://github.com/neon-bindings/cargo-cp-artifact) utility to run the Rust build and copy the built library into `./index.node`.
|
||||
|
||||
## Exploring zk-regex-apis
|
||||
|
||||
After building zk-regex-apis, you can explore its exports at the Node REPL:
|
||||
|
||||
```sh
|
||||
$ npm install
|
||||
$ node
|
||||
> require('.').hello()
|
||||
"hello node"
|
||||
```
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm install`
|
||||
|
||||
Installs the project, including running `npm run build`.
|
||||
|
||||
### `npm build`
|
||||
|
||||
Builds the Node addon (`index.node`) from source.
|
||||
|
||||
Additional [`cargo build`](https://doc.rust-lang.org/cargo/commands/cargo-build.html) arguments may be passed to `npm build` and `npm build-*` commands. For example, to enable a [cargo feature](https://doc.rust-lang.org/cargo/reference/features.html):
|
||||
|
||||
```
|
||||
npm run build -- --feature=beetle
|
||||
```
|
||||
|
||||
#### `npm build-debug`
|
||||
|
||||
Alias for `npm build`.
|
||||
|
||||
#### `npm build-release`
|
||||
|
||||
Same as [`npm build`](#npm-build) but, builds the module with the [`release`](https://doc.rust-lang.org/cargo/reference/profiles.html#release) profile. Release builds will compile slower, but run faster.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Runs the unit tests by calling `cargo test`. You can learn more about [adding tests to your Rust code](https://doc.rust-lang.org/book/ch11-01-writing-tests.html) from the [Rust book](https://doc.rust-lang.org/book/).
|
||||
|
||||
## Project Layout
|
||||
|
||||
The directory structure of this project is:
|
||||
|
||||
```
|
||||
zk-regex-apis/
|
||||
├── Cargo.toml
|
||||
├── README.md
|
||||
├── index.node
|
||||
├── package.json
|
||||
├── src/
|
||||
| └── lib.rs
|
||||
└── target/
|
||||
```
|
||||
|
||||
### Cargo.toml
|
||||
|
||||
The Cargo [manifest file](https://doc.rust-lang.org/cargo/reference/manifest.html), which informs the `cargo` command.
|
||||
|
||||
### README.md
|
||||
|
||||
This file.
|
||||
|
||||
### index.node
|
||||
|
||||
The Node addon—i.e., a binary Node module—generated by building the project. This is the main module for this package, as dictated by the `"main"` key in `package.json`.
|
||||
|
||||
Under the hood, a [Node addon](https://nodejs.org/api/addons.html) is a [dynamically-linked shared object](https://en.wikipedia.org/wiki/Library_(computing)#Shared_libraries). The `"build"` script produces this file by copying it from within the `target/` directory, which is where the Rust build produces the shared object.
|
||||
|
||||
### package.json
|
||||
|
||||
The npm [manifest file](https://docs.npmjs.com/cli/v7/configuring-npm/package-json), which informs the `npm` command.
|
||||
|
||||
### src/
|
||||
|
||||
The directory tree containing the Rust source code for the project.
|
||||
|
||||
### src/lib.rs
|
||||
|
||||
The Rust library's main module.
|
||||
|
||||
### target/
|
||||
|
||||
Binary artifacts generated by the Rust build.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Neon, see the [Neon documentation](https://neon-bindings.com).
|
||||
|
||||
To learn more about Rust, see the [Rust documentation](https://www.rust-lang.org).
|
||||
|
||||
To learn more about Node, see the [Node documentation](https://nodejs.org).
|
||||
18
packages/compiler/package.json
Normal file
18
packages/compiler/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "zk-regex-compiler",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.node",
|
||||
"scripts": {
|
||||
"build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
|
||||
"build-debug": "npm run build --",
|
||||
"build-release": "npm run build -- --release",
|
||||
"install": "npm run build-release",
|
||||
"test": "cargo test"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"cargo-cp-artifact": "^0.1"
|
||||
}
|
||||
}
|
||||
125
packages/compiler/src/bin/compiler.rs
Normal file
125
packages/compiler/src/bin/compiler.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use std::{
|
||||
fs::File,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use itertools::Itertools;
|
||||
use zk_regex_compiler::*;
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand, Clone)]
|
||||
enum Commands {
|
||||
Decomposed {
|
||||
#[arg(short, long)]
|
||||
decomposed_regex_path: String,
|
||||
#[arg(short, long)]
|
||||
halo2_dir_path: Option<String>,
|
||||
#[arg(long)]
|
||||
circom_file_path: Option<String>,
|
||||
#[arg(long)]
|
||||
circom_template_name: Option<String>,
|
||||
#[arg(short, long)]
|
||||
gen_substrs: Option<bool>,
|
||||
},
|
||||
Raw {
|
||||
#[arg(short, long)]
|
||||
raw_regex: String,
|
||||
#[arg(short, long)]
|
||||
max_bytes: usize,
|
||||
#[arg(short, long)]
|
||||
substrs_json_path: Option<String>,
|
||||
#[arg(short, long)]
|
||||
halo2_dir_path: Option<String>,
|
||||
#[arg(long)]
|
||||
circom_file_path: Option<String>,
|
||||
#[arg(long)]
|
||||
circom_template_name: Option<String>,
|
||||
#[arg(short, long)]
|
||||
gen_substrs: Option<bool>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
match cli.command {
|
||||
Commands::Decomposed {
|
||||
decomposed_regex_path,
|
||||
halo2_dir_path,
|
||||
circom_file_path,
|
||||
circom_template_name,
|
||||
gen_substrs,
|
||||
} => {
|
||||
gen_from_decomposed(
|
||||
&decomposed_regex_path,
|
||||
halo2_dir_path.as_ref().map(|s| s.as_str()),
|
||||
circom_file_path.as_ref().map(|s| s.as_str()),
|
||||
circom_template_name.as_ref().map(|s| s.as_str()),
|
||||
gen_substrs,
|
||||
);
|
||||
}
|
||||
Commands::Raw {
|
||||
raw_regex,
|
||||
max_bytes,
|
||||
substrs_json_path,
|
||||
halo2_dir_path,
|
||||
circom_file_path,
|
||||
circom_template_name,
|
||||
gen_substrs,
|
||||
} => {
|
||||
gen_from_raw(
|
||||
&raw_regex,
|
||||
max_bytes,
|
||||
substrs_json_path.as_ref().map(|s| s.as_str()),
|
||||
halo2_dir_path.as_ref().map(|s| s.as_str()),
|
||||
circom_file_path.as_ref().map(|s| s.as_str()),
|
||||
circom_template_name.as_ref().map(|s| s.as_str()),
|
||||
gen_substrs,
|
||||
);
|
||||
} // Commands::GenHalo2Texts {
|
||||
// decomposed_regex_path,
|
||||
// allstr_file_path,
|
||||
// substrs_dir_path,
|
||||
// } => {
|
||||
// let regex_decomposed: DecomposedRegexConfig =
|
||||
// serde_json::from_reader(File::open(decomposed_regex_path).unwrap()).unwrap();
|
||||
// let num_public_part = regex_decomposed
|
||||
// .parts
|
||||
// .iter()
|
||||
// .filter(|part| part.is_public)
|
||||
// .collect_vec()
|
||||
// .len();
|
||||
// let substr_file_pathes = (0..num_public_part)
|
||||
// .map(|idx| {
|
||||
// PathBuf::new()
|
||||
// .join(&substrs_dir_path)
|
||||
// .join(&format!("substr{}.txt", idx))
|
||||
// })
|
||||
// .collect_vec();
|
||||
// regex_decomposed
|
||||
// .gen_regex_files(
|
||||
// &Path::new(&allstr_file_path).to_path_buf(),
|
||||
// &substr_file_pathes,
|
||||
// )
|
||||
// .unwrap();
|
||||
// }
|
||||
// Commands::GenCircom {
|
||||
// decomposed_regex_path,
|
||||
// circom_file_path,
|
||||
// template_name,
|
||||
// } => {
|
||||
// let regex_decomposed: DecomposedRegexConfig =
|
||||
// serde_json::from_reader(File::open(decomposed_regex_path).unwrap()).unwrap();
|
||||
// let circom_path = PathBuf::from(circom_file_path);
|
||||
// regex_decomposed
|
||||
// .gen_circom(&circom_path, &template_name)
|
||||
// .unwrap();
|
||||
// }
|
||||
}
|
||||
}
|
||||
83
packages/compiler/src/circom.rs
Normal file
83
packages/compiler/src/circom.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use super::CompilerError;
|
||||
use crate::get_accepted_state;
|
||||
use crate::js_caller::*;
|
||||
use crate::RegexAndDFA;
|
||||
// use crate::{AllstrRegexDef, SubstrRegexDef};
|
||||
use fancy_regex::Regex;
|
||||
use itertools::Itertools;
|
||||
use petgraph::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, fs::File};
|
||||
use thiserror::Error;
|
||||
|
||||
impl RegexAndDFA {
|
||||
pub fn gen_circom(
|
||||
&self,
|
||||
circom_path: &PathBuf,
|
||||
template_name: &str,
|
||||
gen_substrs: bool,
|
||||
) -> Result<(), CompilerError> {
|
||||
let all_regex = String::new();
|
||||
let circom = gen_circom_allstr(&self.dfa_val, template_name)?;
|
||||
if gen_substrs {
|
||||
self.add_substrs_constraints(circom_path, circom)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_substrs_constraints(
|
||||
&self,
|
||||
circom_path: &PathBuf,
|
||||
mut circom: String,
|
||||
) -> Result<(), CompilerError> {
|
||||
let accepted_state =
|
||||
get_accepted_state(&self.dfa_val).ok_or(JsCallerError::NoAcceptedState)?;
|
||||
circom += "\n";
|
||||
circom += "\tsignal is_consecutive[msg_bytes+1][2];\n";
|
||||
circom += "\tis_consecutive[msg_bytes][1] <== 1;\n";
|
||||
circom += "\tfor (var i = 0; i < msg_bytes; i++) {\n";
|
||||
circom += &format!("\t\tis_consecutive[msg_bytes-1-i][0] <== states[num_bytes-i][{}] * (1 - is_consecutive[msg_bytes-i][1]) + is_consecutive[msg_bytes-i][1];\n",accepted_state);
|
||||
circom += "\t\tis_consecutive[msg_bytes-1-i][1] <== state_changed[msg_bytes-i].out * is_consecutive[msg_bytes-1-i][0];\n";
|
||||
circom += "\t}\n";
|
||||
|
||||
let substr_defs_array = &self.substrs_defs.substr_defs_array;
|
||||
for (idx, defs) in substr_defs_array.into_iter().enumerate() {
|
||||
let num_defs = defs.len();
|
||||
circom += &format!("\tsignal is_substr{}[msg_bytes][{}];\n", idx, num_defs + 1);
|
||||
circom += &format!("\tsignal is_reveal{}[msg_bytes];\n", idx);
|
||||
circom += &format!("\tsignal output reveal{}[msg_bytes];\n", idx);
|
||||
circom += "\tfor (var i = 0; i < msg_bytes; i++) {\n";
|
||||
circom += &format!("\t\tis_substr{}[i][0] <== 0;\n", idx);
|
||||
for (j, (cur, next)) in defs.iter().enumerate() {
|
||||
circom += &format!(
|
||||
"\t\tis_substr{}[i][{}] <== is_substr{}[i][{}] + ",
|
||||
idx,
|
||||
j + 1,
|
||||
idx,
|
||||
j
|
||||
);
|
||||
circom += &format!("states[i+1][{}] * states[i+2][{}];\n", cur, next);
|
||||
// if j != defs.len() - 1 {
|
||||
// circom += " + ";
|
||||
// } else {
|
||||
// circom += ";\n";
|
||||
// }
|
||||
}
|
||||
circom += &format!(
|
||||
"\t\tis_reveal{}[i] <== is_substr{}[i][{}] * is_consecutive[i][1];\n",
|
||||
idx, idx, num_defs
|
||||
);
|
||||
circom += &format!("\t\treveal{}[i] <== in[i+1] * is_reveal{}[i];\n", idx, idx);
|
||||
circom += "\t}\n";
|
||||
}
|
||||
circom += "}";
|
||||
let mut circom_file = File::create(circom_path)?;
|
||||
write!(circom_file, "{}", circom)?;
|
||||
circom_file.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
233
packages/compiler/src/gen_circom.js
Normal file
233
packages/compiler/src/gen_circom.js
Normal file
@@ -0,0 +1,233 @@
|
||||
function genCircomAllstr(graph_json, template_name) {
|
||||
const N = graph_json.length;
|
||||
// const graph = Array(N).fill({});
|
||||
const rev_graph = [];
|
||||
const to_init_graph = [];
|
||||
let init_going_state = null;
|
||||
for (let i = 0; i < N; i++) {
|
||||
rev_graph.push({});
|
||||
to_init_graph.push([]);
|
||||
}
|
||||
let accept_nodes = new Set();
|
||||
for (let i = 0; i < N; i++) {
|
||||
for (let k in graph_json[i]["edges"]) {
|
||||
const v = graph_json[i]["edges"][k];
|
||||
rev_graph[v][i] = Array.from(JSON.parse(k)).map(c => c.charCodeAt());
|
||||
if (i == 0) {
|
||||
const index = rev_graph[v][i].indexOf(94);
|
||||
if (index != -1) {
|
||||
init_going_state = v;
|
||||
rev_graph[v][i][index] = 128;
|
||||
}
|
||||
for (let j = 0; j < rev_graph[v][i].length; j++) {
|
||||
if (rev_graph[v][i][j] == 128) {
|
||||
continue;
|
||||
}
|
||||
to_init_graph[v].push(rev_graph[v][i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (graph_json[i]["type"] == "accept") {
|
||||
accept_nodes.add(i);
|
||||
}
|
||||
}
|
||||
if (init_going_state != null) {
|
||||
for (const [going_state, chars] of Object.entries(to_init_graph)) {
|
||||
if (chars.length == 0) {
|
||||
continue;
|
||||
}
|
||||
if (rev_graph[going_state][init_going_state] == null) {
|
||||
rev_graph[going_state][init_going_state] = [];
|
||||
}
|
||||
rev_graph[going_state][init_going_state] = rev_graph[going_state][init_going_state].concat(chars);
|
||||
}
|
||||
}
|
||||
|
||||
if (accept_nodes[0] != null) {
|
||||
throw new Error("accept node must not be 0");
|
||||
}
|
||||
accept_nodes = [...accept_nodes];
|
||||
if (accept_nodes.length != 1) {
|
||||
throw new Error("the size of accept nodes must be one");
|
||||
}
|
||||
|
||||
let eq_i = 0;
|
||||
let lt_i = 0;
|
||||
let and_i = 0;
|
||||
let multi_or_i = 0;
|
||||
|
||||
let lines = [];
|
||||
lines.push("\tfor (var i = 0; i < num_bytes; i++) {");
|
||||
|
||||
const uppercase = new Set(Array.from("ABCDEFGHIJKLMNOPQRSTUVWXYZ").map(c => c.charCodeAt()));
|
||||
const lowercase = new Set(Array.from("abcdefghijklmnopqrstuvwxyz").map(c => c.charCodeAt()));
|
||||
const digits = new Set(Array.from("0123456789").map(c => c.charCodeAt()));
|
||||
const symbols1 = new Set([":", ";", "<", "=", ">", "?", "@"].map(c => c.charCodeAt()));
|
||||
const symbols2 = new Set(["[", "\\", "]", "^", "_", "`"].map(c => c.charCodeAt()));
|
||||
const symbols3 = new Set(["{", "|", "}", "~"].map(c => c.charCodeAt()));
|
||||
lines.push(`\t\tstate_changed[i] = MultiOR(${N - 1});`);
|
||||
for (let i = 1; i < N; i++) {
|
||||
const outputs = [];
|
||||
for (let prev_i of Object.keys(rev_graph[i])) {
|
||||
const k = rev_graph[i][prev_i];
|
||||
const eq_outputs = [];
|
||||
const vals = new Set(k);
|
||||
if (vals.size == 0) {
|
||||
continue;
|
||||
}
|
||||
const min_maxs = [];
|
||||
for (let subsets of [
|
||||
[digits, 47, 58],
|
||||
[symbols1, 57, 65],
|
||||
[uppercase, 64, 91],
|
||||
[symbols2, 90, 97],
|
||||
[lowercase, 96, 123],
|
||||
[symbols3, 122, 127]
|
||||
]) {
|
||||
const subset = subsets[0];
|
||||
const min = subsets[1];
|
||||
const max = subsets[2];
|
||||
if (vals.isSuperset(subset)) {
|
||||
vals.difference(subset);
|
||||
if (min_maxs.length == 0) {
|
||||
min_maxs.push([min, max]);
|
||||
} else {
|
||||
const last = min_maxs[min_maxs.length - 1];
|
||||
if (last[1] - 1 == min) {
|
||||
min_maxs[min_maxs.length - 1][1] = max;
|
||||
} else {
|
||||
min_maxs.push([min, max]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let min_max of min_maxs) {
|
||||
lines.push(`\t\tlt[${lt_i}][i] = LessThan(8);`);
|
||||
lines.push(`\t\tlt[${lt_i}][i].in[0] <== ${min_max[0]};`);
|
||||
lines.push(`\t\tlt[${lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
lines.push(`\t\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\t\tlt[${lt_i + 1}][i].in[0] <== in[i];`);
|
||||
lines.push(`\t\tlt[${lt_i + 1}][i].in[1] <== ${min_max[1]};`);
|
||||
|
||||
lines.push(`\t\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\t\tand[${and_i}][i].a <== lt[${lt_i}][i].out;`);
|
||||
lines.push(`\t\tand[${and_i}][i].b <== lt[${lt_i + 1}][i].out;`);
|
||||
|
||||
eq_outputs.push(['and', and_i]);
|
||||
lt_i += 2
|
||||
and_i += 1
|
||||
}
|
||||
|
||||
for (let code of vals) {
|
||||
lines.push(`\t\teq[${eq_i}][i] = IsEqual();`);
|
||||
lines.push(`\t\teq[${eq_i}][i].in[0] <== in[i];`);
|
||||
lines.push(`\t\teq[${eq_i}][i].in[1] <== ${code};`);
|
||||
eq_outputs.push(['eq', eq_i]);
|
||||
eq_i += 1
|
||||
}
|
||||
|
||||
lines.push(`\t\tand[${and_i}][i] = AND();`);
|
||||
lines.push(`\t\tand[${and_i}][i].a <== states[i][${prev_i}];`);
|
||||
if (eq_outputs.length == 1) {
|
||||
lines.push(`\t\tand[${and_i}][i].b <== ${eq_outputs[0][0]}[${eq_outputs[0][1]}][i].out;`);
|
||||
} else if (eq_outputs.length > 1) {
|
||||
lines.push(`\t\tmulti_or[${multi_or_i}][i] = MultiOR(${eq_outputs.length});`);
|
||||
for (let output_i = 0; output_i < eq_outputs.length; output_i++) {
|
||||
lines.push(`\t\tmulti_or[${multi_or_i}][i].in[${output_i}] <== ${eq_outputs[output_i][0]}[${eq_outputs[output_i][1]}][i].out;`);
|
||||
}
|
||||
lines.push(`\t\tand[${and_i}][i].b <== multi_or[${multi_or_i}][i].out;`);
|
||||
multi_or_i += 1
|
||||
}
|
||||
|
||||
outputs.push(and_i);
|
||||
and_i += 1;
|
||||
}
|
||||
|
||||
if (outputs.length == 1) {
|
||||
lines.push(`\t\tstates[i+1][${i}] <== and[${outputs[0]}][i].out;`);
|
||||
} else if (outputs.length > 1) {
|
||||
lines.push(`\t\tmulti_or[${multi_or_i}][i] = MultiOR(${outputs.length});`);
|
||||
for (let output_i = 0; output_i < outputs.length; output_i++) {
|
||||
lines.push(`\t\tmulti_or[${multi_or_i}][i].in[${output_i}] <== and[${outputs[output_i]}][i].out;`);
|
||||
}
|
||||
lines.push(`\t\tstates[i+1][${i}] <== multi_or[${multi_or_i}][i].out;`);
|
||||
multi_or_i += 1
|
||||
}
|
||||
lines.push(`\t\tstate_changed[i].in[${i - 1}] <== states[i+1][${i}];`);
|
||||
}
|
||||
lines.push(`\t\tstates[i+1][0] <== 1 - state_changed[i].out;`);
|
||||
lines.push("\t}");
|
||||
|
||||
|
||||
const declarations = [];
|
||||
declarations.push(`pragma circom 2.1.5;\n`);
|
||||
declarations.push(`include "zk-regex-circom/circuits/regex_helpers.circom";\n`);
|
||||
// declarations.push(`pragma circom 2.1.5;\ninclude "@zk-email/circuits/regexes/regex_helpers.circom";\n`);
|
||||
declarations.push(`template ${template_name}(msg_bytes) {`);
|
||||
declarations.push(`\tsignal input msg[msg_bytes];`);
|
||||
declarations.push(`\tsignal output out;\n`);
|
||||
declarations.push(`\tvar num_bytes = msg_bytes+1;`);
|
||||
declarations.push(`\tsignal in[num_bytes];`);
|
||||
declarations.push(`\tin[0]<==128;`);
|
||||
declarations.push(`\tfor (var i = 0; i < msg_bytes; i++) {`);
|
||||
declarations.push(`\t\tin[i+1] <== msg[i];`);
|
||||
declarations.push(`\t}\n`);
|
||||
if (eq_i > 0) {
|
||||
declarations.push(`\tcomponent eq[${eq_i}][num_bytes];`);
|
||||
}
|
||||
if (lt_i > 0) {
|
||||
declarations.push(`\tcomponent lt[${lt_i}][num_bytes];`);
|
||||
}
|
||||
if (and_i > 0) {
|
||||
declarations.push(`\tcomponent and[${and_i}][num_bytes];`);
|
||||
}
|
||||
if (multi_or_i > 0) {
|
||||
declarations.push(`\tcomponent multi_or[${multi_or_i}][num_bytes];`);
|
||||
}
|
||||
declarations.push(`\tsignal states[num_bytes+1][${N}];`);
|
||||
declarations.push(`\tcomponent state_changed[num_bytes];`);
|
||||
declarations.push("");
|
||||
|
||||
const init_code = [];
|
||||
init_code.push(`\tstates[0][0] <== 1;`);
|
||||
init_code.push(`\tfor (var i = 1; i < ${N}; i++) {`);
|
||||
init_code.push(`\t\tstates[0][i] <== 0;`);
|
||||
init_code.push("\t}");
|
||||
init_code.push("");
|
||||
|
||||
lines = declarations.concat(init_code).concat(lines);
|
||||
|
||||
const accept_node = accept_nodes[0];
|
||||
const accept_lines = [""];
|
||||
accept_lines.push("\tcomponent final_state_result = MultiOR(num_bytes+1);");
|
||||
accept_lines.push("\tfor (var i = 0; i <= num_bytes; i++) {");
|
||||
accept_lines.push(`\t\tfinal_state_result.in[i] <== states[i][${accept_node}];`);
|
||||
accept_lines.push("\t}");
|
||||
accept_lines.push("\tout <== final_state_result.out;");
|
||||
|
||||
lines = lines.concat(accept_lines);
|
||||
let string = lines.reduce((res, line) => res + line + "\n", "");
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Set.prototype.isSuperset = function (subset) {
|
||||
if (this.size == 0) {
|
||||
return false;
|
||||
}
|
||||
for (var elem of subset) {
|
||||
if (!this.has(elem)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Set.prototype.difference = function (setB) {
|
||||
for (let elem of setB) {
|
||||
this.delete(elem)
|
||||
}
|
||||
}
|
||||
104
packages/compiler/src/halo2.rs
Normal file
104
packages/compiler/src/halo2.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
use crate::js_caller::*;
|
||||
use crate::*;
|
||||
use fancy_regex::Regex;
|
||||
use itertools::Itertools;
|
||||
use petgraph::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashSet;
|
||||
use std::io::BufWriter;
|
||||
use std::io::Write;
|
||||
use std::iter::FromIterator;
|
||||
use std::path::PathBuf;
|
||||
use std::{collections::HashMap, fs::File};
|
||||
use thiserror::Error;
|
||||
|
||||
impl RegexAndDFA {
|
||||
pub fn gen_halo2_tables(
|
||||
&self,
|
||||
allstr_file_path: &PathBuf,
|
||||
substr_file_pathes: &[PathBuf],
|
||||
gen_substrs: bool,
|
||||
) -> Result<(), CompilerError> {
|
||||
let regex_text = self.dfa_to_regex_def_text()?;
|
||||
let mut regex_file = File::create(allstr_file_path)?;
|
||||
write!(regex_file, "{}", regex_text)?;
|
||||
regex_file.flush()?;
|
||||
if !gen_substrs {
|
||||
return Ok(());
|
||||
}
|
||||
let substr_endpoints_array = self.substrs_defs.substr_endpoints_array.as_ref().unwrap();
|
||||
let max_bytes = self.substrs_defs.max_bytes.as_ref().unwrap();
|
||||
for (idx, defs) in self.substrs_defs.substr_defs_array.iter().enumerate() {
|
||||
let mut writer = BufWriter::new(File::create(&substr_file_pathes[idx])?);
|
||||
let max_size = max_bytes[idx];
|
||||
writer.write_fmt(format_args!("{}\n", &max_size))?;
|
||||
writer.write_fmt(format_args!("0\n{}\n", self.max_byte_size - 1))?;
|
||||
let mut starts_str = "".to_string();
|
||||
let starts = substr_endpoints_array[idx]
|
||||
.0
|
||||
.iter()
|
||||
.sorted_by(|a, b| a.cmp(b));
|
||||
for start in starts {
|
||||
starts_str += &format!("{} ", start);
|
||||
}
|
||||
writer.write_fmt(format_args!("{}\n", starts_str))?;
|
||||
let mut ends_str = "".to_string();
|
||||
let ends = substr_endpoints_array[idx]
|
||||
.1
|
||||
.iter()
|
||||
.sorted_by(|a, b| a.cmp(b));
|
||||
for end in ends {
|
||||
ends_str += &format!("{} ", end);
|
||||
}
|
||||
writer.write_fmt(format_args!("{}\n", ends_str))?;
|
||||
let mut defs = defs.iter().collect::<Vec<&(usize, usize)>>();
|
||||
defs.sort_by(|a, b| {
|
||||
let start_cmp = a.0.cmp(&b.0);
|
||||
let end_cmp = a.1.cmp(&b.1);
|
||||
if start_cmp == std::cmp::Ordering::Equal {
|
||||
end_cmp
|
||||
} else {
|
||||
start_cmp
|
||||
}
|
||||
});
|
||||
for (cur, next) in defs.iter() {
|
||||
writer.write_fmt(format_args!("{} {}\n", cur, next))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dfa_to_regex_def_text(&self) -> Result<String, JsCallerError> {
|
||||
let accepted_state =
|
||||
get_accepted_state(&self.dfa_val).ok_or(JsCallerError::NoAcceptedState)?;
|
||||
let max_state = get_max_state(&self.dfa_val)?;
|
||||
let mut text = "0\n".to_string();
|
||||
text += &format!("{}\n", accepted_state.to_string());
|
||||
text += &format!("{}\n", max_state.to_string());
|
||||
for (i, val) in self.dfa_val.iter().enumerate() {
|
||||
for (key, next_node_val) in val["edges"]
|
||||
.as_object()
|
||||
.ok_or(JsCallerError::InvalidEdges(val["edges"].clone()))?
|
||||
.iter()
|
||||
{
|
||||
let key_list: Vec<String> = serde_json::from_str(&key)?;
|
||||
for key_char in key_list.iter() {
|
||||
let key_char: char = key_char.chars().collect::<Vec<char>>()[0];
|
||||
let next_node = next_node_val
|
||||
.as_u64()
|
||||
.ok_or(JsCallerError::InvalidNodeValue(next_node_val.clone()))?
|
||||
as usize;
|
||||
// println!("i {} next {} char {}", i, next_node, key_char as u8);
|
||||
text += &format!(
|
||||
"{} {} {}\n",
|
||||
i.to_string(),
|
||||
next_node.to_string(),
|
||||
(key_char as u8).to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(text)
|
||||
}
|
||||
}
|
||||
55
packages/compiler/src/js_caller.rs
Normal file
55
packages/compiler/src/js_caller.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use js_sandbox::{AnyError, JsError, Script};
|
||||
use petgraph::prelude::*;
|
||||
use serde_json::Value;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum JsCallerError {
|
||||
#[error("Edges {0} are not object")]
|
||||
InvalidEdges(Value),
|
||||
#[error("node value {0} is not u64")]
|
||||
InvalidNodeValue(Value),
|
||||
#[error("No accepted state")]
|
||||
NoAcceptedState,
|
||||
#[error(transparent)]
|
||||
JsError(#[from] JsError),
|
||||
#[error(transparent)]
|
||||
JsonError(#[from] serde_json::Error),
|
||||
}
|
||||
|
||||
pub fn catch_all_regex_str() -> Result<String, JsCallerError> {
|
||||
let code: &'static str = include_str!("regex.js");
|
||||
let mut script = Script::from_string(code)?;
|
||||
let result: String = script.call("catchAllRegexStr", ())?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn text_context_prefix() -> Result<String, JsCallerError> {
|
||||
let code: &'static str = include_str!("regex.js");
|
||||
let mut script = Script::from_string(code)?;
|
||||
let result: String = script.call("textContextPrefix", ())?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
// pub fn format_regex_printable(regex: &str) -> Result<String, JsCallerError> {
|
||||
// let code: &'static str = include_str!("regex.js");
|
||||
// let mut script = Script::from_string(code)?;
|
||||
// let result: String = script.call("formatRegexPrintable", (regex,))?;
|
||||
// Ok(result)
|
||||
// }
|
||||
|
||||
pub fn regex_to_dfa(regex: &str) -> Result<Vec<Value>, JsCallerError> {
|
||||
let code: &'static str = include_str!("regex.js");
|
||||
let mut script = Script::from_string(code)?;
|
||||
let result: String = script.call("regexToDfa", (regex,))?;
|
||||
Ok(serde_json::from_str(&result)?)
|
||||
}
|
||||
|
||||
pub fn gen_circom_allstr(graph: &[Value], template_name: &str) -> Result<String, JsCallerError> {
|
||||
let code: &'static str = include_str!("gen_circom.js");
|
||||
let mut script = Script::from_string(code)?;
|
||||
let result: String = script.call("genCircomAllstr", (graph, template_name))?;
|
||||
Ok(result)
|
||||
}
|
||||
470
packages/compiler/src/lib.rs
Normal file
470
packages/compiler/src/lib.rs
Normal file
@@ -0,0 +1,470 @@
|
||||
use std::iter::FromIterator;
|
||||
use std::{collections::HashMap, fs::File};
|
||||
pub mod circom;
|
||||
pub mod halo2;
|
||||
pub mod js_caller;
|
||||
|
||||
#[cfg(feature = "node")]
|
||||
pub mod node;
|
||||
#[cfg(feature = "node")]
|
||||
use crate::node::*;
|
||||
#[cfg(feature = "node")]
|
||||
use neon;
|
||||
|
||||
use crate::js_caller::*;
|
||||
use fancy_regex::Regex;
|
||||
use itertools::Itertools;
|
||||
use petgraph::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error definitions of the compiler.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CompilerError {
|
||||
#[error("No edge from {:?} to {:?} in the graph",.0,.1)]
|
||||
NoEdge(NodeIndex<usize>, NodeIndex<usize>),
|
||||
#[error(transparent)]
|
||||
JsCallerError(#[from] JsCallerError),
|
||||
#[error(transparent)]
|
||||
IoError(#[from] std::io::Error),
|
||||
#[error(transparent)]
|
||||
RegexError(#[from] fancy_regex::Error),
|
||||
}
|
||||
|
||||
/// A configuration of decomposed regexes.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DecomposedRegexConfig {
|
||||
/// Maximum byte size of the input string.
|
||||
pub max_byte_size: usize,
|
||||
/// A vector of decomposed regexes.
|
||||
pub parts: Vec<RegexPartConfig>,
|
||||
}
|
||||
|
||||
/// Decomposed regex part.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RegexPartConfig {
|
||||
/// A flag indicating whether the substring matching with `regex_def` should be exposed.
|
||||
pub is_public: bool,
|
||||
/// A regex string.
|
||||
pub regex_def: String,
|
||||
/// Maximum byte size of the substring in this part.
|
||||
pub max_size: usize,
|
||||
/// (Optional) A solidity type of the substring in this part, e.g., "String", "Int", "Decimal".
|
||||
pub solidity: Option<SoldityType>,
|
||||
}
|
||||
/// Solidity type of the substring.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum SoldityType {
|
||||
String,
|
||||
Uint,
|
||||
Decimal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RegexAndDFA {
|
||||
pub max_byte_size: usize,
|
||||
pub all_regex: String,
|
||||
pub dfa_val: Vec<Value>,
|
||||
pub substrs_defs: SubstrsDefs,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubstrsDefs {
|
||||
pub substr_defs_array: Vec<HashSet<(usize, usize)>>,
|
||||
pub substr_endpoints_array: Option<Vec<(HashSet<usize>, HashSet<usize>)>>,
|
||||
pub max_bytes: Option<Vec<usize>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SubstrsDefsJson {
|
||||
pub transitions: Vec<Vec<(usize, usize)>>,
|
||||
}
|
||||
|
||||
impl DecomposedRegexConfig {
|
||||
pub fn to_regex_and_dfa(&self) -> Result<RegexAndDFA, CompilerError> {
|
||||
let mut all_regex = String::new();
|
||||
let part_configs = &self.parts;
|
||||
for config in part_configs.iter() {
|
||||
all_regex += &config.regex_def;
|
||||
}
|
||||
let dfa_val = regex_to_dfa(&all_regex)?;
|
||||
let substrs_defs = self.extract_substr_ids(&dfa_val)?;
|
||||
Ok(RegexAndDFA {
|
||||
max_byte_size: self.max_byte_size,
|
||||
all_regex,
|
||||
dfa_val,
|
||||
substrs_defs,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn extract_substr_ids(&self, dfa_val: &[Value]) -> Result<SubstrsDefs, CompilerError> {
|
||||
let part_configs = &self.parts;
|
||||
let mut graph = Graph::<bool, String, Directed, usize>::with_capacity(0, 0);
|
||||
let max_state = get_max_state(dfa_val)?;
|
||||
add_graph_nodes(dfa_val, &mut graph, None, max_state)?;
|
||||
let accepted_state = get_accepted_state(dfa_val).ok_or(JsCallerError::NoAcceptedState)?;
|
||||
let accepted_state_index = NodeIndex::from(accepted_state);
|
||||
let mut pathes = Vec::<Vec<NodeIndex<usize>>>::new();
|
||||
let mut stack = Vec::<(NodeIndex<usize>, Vec<NodeIndex<usize>>)>::new();
|
||||
stack.push((accepted_state_index, vec![accepted_state_index]));
|
||||
let mut self_nodes = HashSet::new();
|
||||
let mut self_nodes_char = HashMap::new();
|
||||
for state in 0..=max_state {
|
||||
let node = NodeIndex::from(state);
|
||||
if let Some(edge) = graph.find_edge(node, node) {
|
||||
let str = graph.edge_weight(edge).unwrap().as_str();
|
||||
let bytes = str.as_bytes();
|
||||
self_nodes_char.insert(node.index(), bytes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
while stack.len() != 0 {
|
||||
let (node, path) = stack.pop().unwrap();
|
||||
let mut parents = graph.neighbors(node).detach();
|
||||
while let Some((edge, parent)) = parents.next(&graph) {
|
||||
if parent.index() == node.index() {
|
||||
self_nodes.insert(node.index());
|
||||
graph.remove_edge(edge).unwrap();
|
||||
continue;
|
||||
}
|
||||
if !path.contains(&parent) {
|
||||
if parent.index() == 0 {
|
||||
pathes.push(path.to_vec());
|
||||
continue;
|
||||
}
|
||||
stack.push((parent, vec![path.clone(), vec![parent]].concat()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut public_config_indexes: Vec<usize> = vec![];
|
||||
let mut part_regexes = vec![];
|
||||
for (idx, config) in part_configs.iter().enumerate() {
|
||||
if config.is_public {
|
||||
public_config_indexes.push(idx);
|
||||
}
|
||||
if idx == 0 {
|
||||
let regex_def = config.regex_def.replace("^", "\\^");
|
||||
part_regexes.push(Regex::new(®ex_def)?);
|
||||
} else {
|
||||
let pre_regex = part_regexes[idx - 1].to_string();
|
||||
part_regexes.push(Regex::new(&(pre_regex + &config.regex_def))?);
|
||||
}
|
||||
}
|
||||
let num_public_parts = public_config_indexes.len();
|
||||
let mut substr_defs_array = (0..num_public_parts)
|
||||
.map(|_| HashSet::<(usize, usize)>::new())
|
||||
.collect_vec();
|
||||
let mut substr_endpoints_array = (0..num_public_parts)
|
||||
.map(|_| (HashSet::<usize>::new(), HashSet::<usize>::new()))
|
||||
.collect_vec();
|
||||
for path in pathes.iter_mut() {
|
||||
let n = path.len();
|
||||
path.append(&mut vec![NodeIndex::from(0)]);
|
||||
let edges = (0..n)
|
||||
.map(|idx| {
|
||||
graph
|
||||
.find_edge(path[idx], path[idx + 1])
|
||||
.ok_or(CompilerError::NoEdge(path[idx], path[idx + 1]))
|
||||
})
|
||||
.collect::<Result<Vec<EdgeIndex<usize>>, CompilerError>>()?;
|
||||
let string_vec = edges
|
||||
.iter()
|
||||
.map(|edge| graph.edge_weight(*edge).unwrap().as_str())
|
||||
.collect::<Vec<&str>>();
|
||||
let path_states = path
|
||||
.into_iter()
|
||||
.rev()
|
||||
.map(|node| node.index())
|
||||
.collect::<Vec<usize>>();
|
||||
let path_strs = string_vec
|
||||
.iter()
|
||||
.rev()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
let substr_states = self.get_substr_defs_from_path(
|
||||
&path_states,
|
||||
&path_strs,
|
||||
&part_regexes,
|
||||
&public_config_indexes,
|
||||
)?;
|
||||
for (substr_idx, (path_states, substr)) in substr_states.into_iter().enumerate() {
|
||||
let defs = &mut substr_defs_array[substr_idx];
|
||||
substr_endpoints_array[substr_idx].0.insert(path_states[0]);
|
||||
substr_endpoints_array[substr_idx]
|
||||
.1
|
||||
.insert(path_states[path_states.len() - 1]);
|
||||
for path_idx in 0..(path_states.len() - 1) {
|
||||
defs.insert((path_states[path_idx], path_states[path_idx + 1]));
|
||||
if self_nodes.contains(&path_states[path_idx]) {
|
||||
defs.insert((path_states[path_idx], path_states[path_idx]));
|
||||
}
|
||||
for pre_path_idx in 0..=path_idx {
|
||||
if graph
|
||||
.find_edge(
|
||||
NodeIndex::from(path_states[pre_path_idx]),
|
||||
NodeIndex::from(path_states[path_idx + 1]),
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
defs.insert((path_states[path_idx + 1], path_states[pre_path_idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
if self_nodes.contains(&path_states[path_states.len() - 1]) {
|
||||
let part_index = public_config_indexes[substr_idx];
|
||||
let part_regex = &part_regexes[part_index];
|
||||
let byte = self_nodes_char[&path_states[path_states.len() - 1]];
|
||||
let substr = substr + &(byte as char).to_string();
|
||||
if part_regex.is_match(&substr).unwrap() {
|
||||
defs.insert((
|
||||
path_states[path_states.len() - 1],
|
||||
path_states[path_states.len() - 1],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let max_bytes = public_config_indexes
|
||||
.iter()
|
||||
.map(|idx| self.parts[*idx].max_size)
|
||||
.collect_vec();
|
||||
let substrs_defs = SubstrsDefs {
|
||||
substr_defs_array,
|
||||
substr_endpoints_array: Some(substr_endpoints_array),
|
||||
max_bytes: Some(max_bytes),
|
||||
};
|
||||
Ok(substrs_defs)
|
||||
}
|
||||
|
||||
fn get_substr_defs_from_path(
|
||||
&self,
|
||||
path_states: &[usize],
|
||||
path_strs: &[String],
|
||||
part_regexes: &[Regex],
|
||||
public_config_indexes: &[usize],
|
||||
) -> Result<Vec<(Vec<usize>, String)>, CompilerError> {
|
||||
debug_assert_eq!(path_states.len(), path_strs.len() + 1);
|
||||
let mut concat_str = String::new();
|
||||
for str in path_strs.into_iter() {
|
||||
let first_chars = str.as_bytes();
|
||||
concat_str += &(first_chars[0] as char).to_string();
|
||||
}
|
||||
let index_ends = part_regexes
|
||||
.iter()
|
||||
.map(|regex| {
|
||||
let found = regex.find(&concat_str).unwrap().unwrap();
|
||||
if found.start() == found.end() {
|
||||
found.end() + 1
|
||||
} else {
|
||||
found.end()
|
||||
}
|
||||
})
|
||||
.collect_vec();
|
||||
let mut substr_results = vec![];
|
||||
for index in public_config_indexes.iter() {
|
||||
let start = if *index == 0 {
|
||||
0
|
||||
} else {
|
||||
index_ends[index - 1]
|
||||
};
|
||||
let end = index_ends[*index];
|
||||
substr_results.push((
|
||||
path_states[(start)..=end].to_vec(),
|
||||
concat_str[0..=(end - 1)].to_string(),
|
||||
));
|
||||
}
|
||||
Ok(substr_results)
|
||||
}
|
||||
}
|
||||
|
||||
impl RegexAndDFA {
|
||||
pub fn from_regex_str_and_substr_defs(
|
||||
max_byte_size: usize,
|
||||
regex_str: &str,
|
||||
substrs_defs_json: SubstrsDefsJson,
|
||||
) -> Result<RegexAndDFA, CompilerError> {
|
||||
let dfa_val = regex_to_dfa(regex_str)?;
|
||||
let substr_defs_array = substrs_defs_json
|
||||
.transitions
|
||||
.into_iter()
|
||||
.map(|transitions_array| HashSet::<(usize, usize)>::from_iter(transitions_array))
|
||||
.collect_vec();
|
||||
let substrs_defs = SubstrsDefs {
|
||||
substr_defs_array,
|
||||
substr_endpoints_array: None,
|
||||
max_bytes: None,
|
||||
};
|
||||
|
||||
Ok(RegexAndDFA {
|
||||
max_byte_size,
|
||||
all_regex: regex_str.to_string(),
|
||||
dfa_val,
|
||||
substrs_defs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_from_decomposed(
|
||||
decomposed_regex_path: &str,
|
||||
halo2_dir_path: Option<&str>,
|
||||
circom_file_path: Option<&str>,
|
||||
circom_template_name: Option<&str>,
|
||||
gen_substrs: Option<bool>,
|
||||
) {
|
||||
let decomposed_regex_config: DecomposedRegexConfig =
|
||||
serde_json::from_reader(File::open(decomposed_regex_path).unwrap()).unwrap();
|
||||
let regex_and_dfa = decomposed_regex_config
|
||||
.to_regex_and_dfa()
|
||||
.expect("failed to convert the decomposed regex to dfa");
|
||||
let gen_substrs = gen_substrs.unwrap_or(true);
|
||||
if let Some(halo2_dir_path) = halo2_dir_path {
|
||||
let halo2_dir_path = PathBuf::from(halo2_dir_path);
|
||||
let allstr_file_path = halo2_dir_path.join("allstr.txt");
|
||||
let mut num_public_parts = 0usize;
|
||||
for part in decomposed_regex_config.parts.iter() {
|
||||
if part.is_public {
|
||||
num_public_parts += 1;
|
||||
}
|
||||
}
|
||||
let substr_file_pathes = (0..num_public_parts)
|
||||
.map(|idx| halo2_dir_path.join(format!("substr_{}.txt", idx)))
|
||||
.collect_vec();
|
||||
regex_and_dfa
|
||||
.gen_halo2_tables(&allstr_file_path, &substr_file_pathes, gen_substrs)
|
||||
.expect("failed to generate halo2 tables");
|
||||
}
|
||||
if let Some(circom_file_path) = circom_file_path {
|
||||
let circom_file_path = PathBuf::from(circom_file_path);
|
||||
let circom_template_name = circom_template_name
|
||||
.expect("circom template name must be specified if circom file path is specified");
|
||||
regex_and_dfa
|
||||
.gen_circom(&circom_file_path, &circom_template_name, gen_substrs)
|
||||
.expect("failed to generate circom");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_from_raw(
|
||||
raw_regex: &str,
|
||||
max_bytes: usize,
|
||||
substrs_json_path: Option<&str>,
|
||||
halo2_dir_path: Option<&str>,
|
||||
circom_file_path: Option<&str>,
|
||||
circom_template_name: Option<&str>,
|
||||
gen_substrs: Option<bool>,
|
||||
) {
|
||||
let substrs_defs_json = if let Some(substrs_json_path) = substrs_json_path {
|
||||
let substrs_json_path = PathBuf::from(substrs_json_path);
|
||||
let substrs_defs_json: SubstrsDefsJson =
|
||||
serde_json::from_reader(File::open(substrs_json_path).unwrap()).unwrap();
|
||||
substrs_defs_json
|
||||
} else {
|
||||
SubstrsDefsJson {
|
||||
transitions: vec![vec![]],
|
||||
}
|
||||
};
|
||||
let num_public_parts = substrs_defs_json.transitions.len();
|
||||
let regex_and_dfa =
|
||||
RegexAndDFA::from_regex_str_and_substr_defs(max_bytes, raw_regex, substrs_defs_json)
|
||||
.expect("failed to convert the raw regex and state transitions to dfa");
|
||||
let gen_substrs = gen_substrs.unwrap_or(true);
|
||||
if let Some(halo2_dir_path) = halo2_dir_path {
|
||||
let halo2_dir_path = PathBuf::from(halo2_dir_path);
|
||||
let allstr_file_path = halo2_dir_path.join("allstr.txt");
|
||||
let substr_file_pathes = (0..num_public_parts)
|
||||
.map(|idx| halo2_dir_path.join(format!("substr_{}.txt", idx)))
|
||||
.collect_vec();
|
||||
regex_and_dfa
|
||||
.gen_halo2_tables(&allstr_file_path, &substr_file_pathes, gen_substrs)
|
||||
.expect("failed to generate halo2 tables");
|
||||
}
|
||||
if let Some(circom_file_path) = circom_file_path {
|
||||
let circom_file_path = PathBuf::from(circom_file_path);
|
||||
let circom_template_name = circom_template_name
|
||||
.expect("circom template name must be specified if circom file path is specified");
|
||||
regex_and_dfa
|
||||
.gen_circom(&circom_file_path, &circom_template_name, gen_substrs)
|
||||
.expect("failed to generate circom");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_accepted_state(dfa_val: &[Value]) -> Option<usize> {
|
||||
for i in 0..dfa_val.len() {
|
||||
if dfa_val[i]["type"] == "accept" {
|
||||
return Some(i as usize);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn get_max_state(dfa_val: &[Value]) -> Result<usize, JsCallerError> {
|
||||
let mut max_state = 0;
|
||||
for (i, val) in dfa_val.iter().enumerate() {
|
||||
for (_, next_node_val) in val["edges"]
|
||||
.as_object()
|
||||
.ok_or(JsCallerError::InvalidEdges(val["edges"].clone()))?
|
||||
.iter()
|
||||
{
|
||||
let next_node = next_node_val
|
||||
.as_u64()
|
||||
.ok_or(JsCallerError::InvalidNodeValue(next_node_val.clone()))?
|
||||
as usize;
|
||||
if next_node > max_state {
|
||||
max_state = next_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(max_state)
|
||||
}
|
||||
|
||||
pub(crate) fn add_graph_nodes(
|
||||
dfa_val: &[Value],
|
||||
graph: &mut Graph<bool, String, Directed, usize>,
|
||||
last_max_state: Option<usize>,
|
||||
next_max_state: usize,
|
||||
) -> Result<(), JsCallerError> {
|
||||
let first_new_state = match last_max_state {
|
||||
Some(v) => v + 1,
|
||||
None => 0,
|
||||
};
|
||||
for idx in first_new_state..=next_max_state {
|
||||
graph.add_node(idx == next_max_state);
|
||||
}
|
||||
|
||||
for (i, val) in dfa_val.iter().enumerate() {
|
||||
for (key, next_node_val) in val["edges"]
|
||||
.as_object()
|
||||
.ok_or(JsCallerError::InvalidEdges(val["edges"].clone()))?
|
||||
.iter()
|
||||
{
|
||||
let next_node = next_node_val
|
||||
.as_u64()
|
||||
.ok_or(JsCallerError::InvalidNodeValue(next_node_val.clone()))?
|
||||
as usize;
|
||||
if let Some(max) = last_max_state {
|
||||
if i <= max && next_node <= max {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let key_list: Vec<String> = serde_json::from_str(&key)?;
|
||||
let mut key_str = String::new();
|
||||
for key_char in key_list.iter() {
|
||||
assert!(key_char.len() == 1);
|
||||
key_str += key_char;
|
||||
}
|
||||
graph.add_edge(NodeIndex::from(next_node), NodeIndex::from(i), key_str);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "node")]
|
||||
#[neon::main]
|
||||
fn main(mut cx: neon::prelude::ModuleContext) -> neon::prelude::NeonResult<()> {
|
||||
cx.export_function("genFromDecomposed", gen_from_decomposed_node)?;
|
||||
Ok(())
|
||||
}
|
||||
35
packages/compiler/src/node.rs
Normal file
35
packages/compiler/src/node.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use crate::gen_from_decomposed;
|
||||
use neon::prelude::*;
|
||||
|
||||
pub(crate) fn gen_from_decomposed_node(mut cx: FunctionContext) -> JsResult<JsNull> {
|
||||
let decomposed_regex_path = cx.argument::<JsString>(0)?.value(&mut cx);
|
||||
let halo2_dir_path = cx.argument_opt(1).map(|v| {
|
||||
v.to_string(&mut cx)
|
||||
.expect("halo2_dir_path must be null or string")
|
||||
.value(&mut cx)
|
||||
});
|
||||
let circom_file_path = cx.argument_opt(2).map(|v| {
|
||||
v.to_string(&mut cx)
|
||||
.expect("circom_file_path must be null or string")
|
||||
.value(&mut cx)
|
||||
});
|
||||
let circom_template_name = cx.argument_opt(3).map(|v| {
|
||||
v.to_string(&mut cx)
|
||||
.expect("circom_template_name must be null or string")
|
||||
.value(&mut cx)
|
||||
});
|
||||
let gen_substrs = cx.argument_opt(4).map(|v| {
|
||||
v.as_value(&mut cx)
|
||||
.downcast::<JsBoolean, _>(&mut cx)
|
||||
.expect("gen_substrs must be null or boolean")
|
||||
.value(&mut cx)
|
||||
});
|
||||
gen_from_decomposed(
|
||||
&decomposed_regex_path,
|
||||
halo2_dir_path.as_ref().map(|s| s.as_str()),
|
||||
circom_file_path.as_ref().map(|s| s.as_str()),
|
||||
circom_template_name.as_ref().map(|s| s.as_str()),
|
||||
gen_substrs,
|
||||
);
|
||||
Ok(cx.null())
|
||||
}
|
||||
@@ -1,6 +1,15 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
/*jslint browser: true*/
|
||||
|
||||
// const a2z_nosep = "abcdefghijklmnopqrstuvwxyz";
|
||||
// const A2Z_nosep = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
// const a2f_nosep = "abcdef";
|
||||
// const A2F_nosep = "ABCDEF";
|
||||
// const r0to9_nosep = "0123456789";
|
||||
// const escapeMap = { n: "\n", r: "\r", t: "\t", v: "\v", f: "\f" };
|
||||
// const whitespace = Object.values(escapeMap);
|
||||
// const slash_s = whitespace.join("|");
|
||||
|
||||
/**
|
||||
* Try parsing simple regular expression to syntax tree.
|
||||
*
|
||||
@@ -26,7 +35,7 @@ function parseRegex(text) {
|
||||
var i,
|
||||
sub,
|
||||
last = 0,
|
||||
node = {'begin': begin, 'end': end},
|
||||
node = { 'begin': begin, 'end': end },
|
||||
virNode,
|
||||
tempNode,
|
||||
stack = 0,
|
||||
@@ -86,7 +95,7 @@ function parseRegex(text) {
|
||||
if (parts.length === 0) {
|
||||
return 'Error: unexpected * at ' + (begin + i) + '.';
|
||||
}
|
||||
tempNode = {'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1};
|
||||
tempNode = { 'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1 };
|
||||
tempNode.type = 'star';
|
||||
tempNode.sub = parts[parts.length - 1];
|
||||
parts[parts.length - 1] = tempNode;
|
||||
@@ -94,10 +103,10 @@ function parseRegex(text) {
|
||||
if (parts.length === 0) {
|
||||
return 'Error: unexpected + at ' + (begin + i) + '.';
|
||||
}
|
||||
virNode = {'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1};
|
||||
virNode = { 'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1 };
|
||||
virNode.type = 'star';
|
||||
virNode.sub = parts[parts.length - 1];
|
||||
tempNode = {'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1};
|
||||
tempNode = { 'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1 };
|
||||
tempNode.type = 'cat';
|
||||
tempNode.parts = [parts[parts.length - 1], virNode];
|
||||
parts[parts.length - 1] = tempNode;
|
||||
@@ -105,24 +114,24 @@ function parseRegex(text) {
|
||||
if (parts.length === 0) {
|
||||
return 'Error: unexpected + at ' + (begin + i) + '.';
|
||||
}
|
||||
virNode = {'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1};
|
||||
virNode = { 'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1 };
|
||||
virNode.type = 'empty';
|
||||
virNode.sub = parts[parts.length - 1];
|
||||
tempNode = {'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1};
|
||||
tempNode = { 'begin': parts[parts.length - 1].begin, 'end': parts[parts.length - 1].end + 1 };
|
||||
tempNode.type = 'or';
|
||||
tempNode.parts = [parts[parts.length - 1], virNode];
|
||||
parts[parts.length - 1] = tempNode;
|
||||
} else if (text[i] === 'ϵ') {
|
||||
tempNode = {'begin': begin + i, 'end': begin + i + 1};
|
||||
tempNode = { 'begin': begin + i, 'end': begin + i + 1 };
|
||||
tempNode.type = 'empty';
|
||||
parts.push(tempNode);
|
||||
} else if (Array.isArray(text[i])) {
|
||||
tempNode = {'begin': begin + i, 'end': begin + i + 1};
|
||||
tempNode = { 'begin': begin + i, 'end': begin + i + 1 };
|
||||
tempNode.type = 'text';
|
||||
tempNode.text = text[i][0];
|
||||
parts.push(tempNode);
|
||||
} else {
|
||||
tempNode = {'begin': begin + i, 'end': begin + i + 1};
|
||||
tempNode = { 'begin': begin + i, 'end': begin + i + 1 };
|
||||
tempNode.type = 'text';
|
||||
tempNode.text = text[i];
|
||||
parts.push(tempNode);
|
||||
@@ -141,7 +150,7 @@ function parseRegex(text) {
|
||||
let i = 0;
|
||||
while (i < text.length) {
|
||||
if (text[i] == '\\') {
|
||||
new_text.push([text[i+1]]);
|
||||
new_text.push([text[i + 1]]);
|
||||
i += 2;
|
||||
} else {
|
||||
new_text.push(text[i]);
|
||||
@@ -166,36 +175,36 @@ function regexToNfa(text) {
|
||||
count += 1;
|
||||
}
|
||||
switch (node.type) {
|
||||
case 'empty':
|
||||
start.edges.push(['ϵ', end]);
|
||||
break;
|
||||
case 'text':
|
||||
start.edges.push([node.text, end]);
|
||||
break;
|
||||
case 'cat':
|
||||
last = start;
|
||||
for (i = 0; i < node.parts.length - 1; i += 1) {
|
||||
temp = {'type': '', 'edges': []};
|
||||
count = generateGraph(node.parts[i], last, temp, count);
|
||||
last = temp;
|
||||
}
|
||||
count = generateGraph(node.parts[node.parts.length - 1], last, end, count);
|
||||
break;
|
||||
case 'or':
|
||||
for (i = 0; i < node.parts.length; i += 1) {
|
||||
tempStart = {'type': '', 'edges': []};
|
||||
tempEnd = {'type': '', 'edges': [['ϵ', end]]};
|
||||
case 'empty':
|
||||
start.edges.push(['ϵ', end]);
|
||||
break;
|
||||
case 'text':
|
||||
start.edges.push([node.text, end]);
|
||||
break;
|
||||
case 'cat':
|
||||
last = start;
|
||||
for (i = 0; i < node.parts.length - 1; i += 1) {
|
||||
temp = { 'type': '', 'edges': [] };
|
||||
count = generateGraph(node.parts[i], last, temp, count);
|
||||
last = temp;
|
||||
}
|
||||
count = generateGraph(node.parts[node.parts.length - 1], last, end, count);
|
||||
break;
|
||||
case 'or':
|
||||
for (i = 0; i < node.parts.length; i += 1) {
|
||||
tempStart = { 'type': '', 'edges': [] };
|
||||
tempEnd = { 'type': '', 'edges': [['ϵ', end]] };
|
||||
start.edges.push(['ϵ', tempStart]);
|
||||
count = generateGraph(node.parts[i], tempStart, tempEnd, count);
|
||||
}
|
||||
break;
|
||||
case 'star':
|
||||
tempStart = { 'type': '', 'edges': [] };
|
||||
tempEnd = { 'type': '', 'edges': [['ϵ', tempStart], ['ϵ', end]] };
|
||||
start.edges.push(['ϵ', tempStart]);
|
||||
count = generateGraph(node.parts[i], tempStart, tempEnd, count);
|
||||
}
|
||||
break;
|
||||
case 'star':
|
||||
tempStart = {'type': '', 'edges': []};
|
||||
tempEnd = {'type': '', 'edges': [['ϵ', tempStart], ['ϵ', end]]};
|
||||
start.edges.push(['ϵ', tempStart]);
|
||||
start.edges.push(['ϵ', end]);
|
||||
count = generateGraph(node.sub, tempStart, tempEnd, count);
|
||||
break;
|
||||
start.edges.push(['ϵ', end]);
|
||||
count = generateGraph(node.sub, tempStart, tempEnd, count);
|
||||
break;
|
||||
}
|
||||
if (!end.hasOwnProperty('id')) {
|
||||
end.id = count;
|
||||
@@ -204,8 +213,8 @@ function regexToNfa(text) {
|
||||
return count;
|
||||
}
|
||||
var ast = parseRegex(text),
|
||||
start = {'type': 'start', 'edges': []},
|
||||
accept = {'type': 'accept', 'edges': []};
|
||||
start = { 'type': 'start', 'edges': [] },
|
||||
accept = { 'type': 'accept', 'edges': [] };
|
||||
if (typeof ast === 'string') {
|
||||
return ast;
|
||||
}
|
||||
@@ -532,20 +541,14 @@ function toNature(col) {
|
||||
// '(\r\n|\x80)(to|from):([A-Za-z0-9 _."@-]+<)?[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.]+>?\r\n';
|
||||
// let regex = '(\r\n|\x80)(to|from):((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9| |_|.|"|@|-)+<)?(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+>?\r\n';
|
||||
|
||||
const key_chars = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)';
|
||||
const catch_all = '(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|/|:|;|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\n|\r|\x0b|\x0c)';
|
||||
const catch_all_without_semicolon = '(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|/|:|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\n|\r|\x0b|\x0c)';
|
||||
const base_64 = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\+|/|=)';
|
||||
const word_char = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_)';
|
||||
// const key_chars = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)';
|
||||
// const catch_all = '(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|/|:|;|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\n|\r|\x0b|\x0c)';
|
||||
// const catch_all_without_semicolon = '(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|/|:|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\n|\r|\x0b|\x0c)';
|
||||
// const base_64 = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\+|/|=)';
|
||||
// const word_char = '(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_)';
|
||||
|
||||
|
||||
function compile(regex) {
|
||||
// let regex = `\r\ndkim-signature:(${key_chars}=${catch_all_without_semicolon}+; )+bh=${base_64}+; `;
|
||||
|
||||
// console.log(regex);
|
||||
// console.log(Buffer.from(regex).toString('base64'));
|
||||
|
||||
// let regex = 'hello(0|1|2|3|4|5|6|7|8|9)+world';
|
||||
function regexToDfa(regex) {
|
||||
let nfa = regexToNfa(regex);
|
||||
let dfa = minDfa(nfaToDfa(nfa));
|
||||
|
||||
@@ -582,20 +585,45 @@ function compile(regex) {
|
||||
curr.edges = {};
|
||||
for (let j = 0; j < symbols.length; j += 1) {
|
||||
if (nodes[i].trans.hasOwnProperty(symbols[j])) {
|
||||
curr.edges[symbols[j]] = nodes[i].trans[symbols[j]].nature-1;
|
||||
curr.edges[symbols[j]] = nodes[i].trans[symbols[j]].nature - 1;
|
||||
}
|
||||
}
|
||||
graph[nodes[i].nature-1] = curr;
|
||||
graph[nodes[i].nature - 1] = curr;
|
||||
}
|
||||
|
||||
return graph;
|
||||
return JSON.stringify(graph);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compile,
|
||||
key_chars,
|
||||
base_64,
|
||||
word_char,
|
||||
catch_all,
|
||||
catch_all_without_semicolon,
|
||||
};
|
||||
|
||||
function catchAllRegexStr() {
|
||||
return "(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|\"|#|$|%|&|'|\\(|\\)|\\*|\\+|,|-|.|/|:|;|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\n|\r|\x0b|\x0c)";
|
||||
}
|
||||
|
||||
function catchAllWithoutRNRegexStr() {
|
||||
return "(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|\"|#|$|%|&|'|\\(|\\)|\\*|\\+|,|-|.|/|:|;|<|=|>|\\?|@|[|\\\\|]|^|_|`|{|\\||}|~| |\t|\x0b|\x0c)";
|
||||
}
|
||||
|
||||
function textContextPrefix() {
|
||||
return `Content-Type: text/plain; charset="UTF-8"\r\n\r\n`;
|
||||
}
|
||||
|
||||
// function formatRegexPrintable(s) {
|
||||
// const escaped_string_json = JSON.stringify(s);
|
||||
// const escaped_string = escaped_string_json.slice(1, escaped_string_json.length - 1);
|
||||
// return escaped_string
|
||||
// .replaceAll("\\\\\\\\", "\\")
|
||||
// .replaceAll("\\\\", "\\")
|
||||
// .replaceAll("/", "\\/")
|
||||
// .replaceAll("\u000b", "\\♥")
|
||||
// .replaceAll("^", "\\^")
|
||||
// .replaceAll("$", "\\$")
|
||||
// .replaceAll("|[|", "|\\[|")
|
||||
// .replaceAll("|]|", "|\\]|")
|
||||
// .replaceAll("|.|", "|\\.|")
|
||||
// .replaceAll("|$|", "|\\$|")
|
||||
// .replaceAll("|^|", "|\\^|");
|
||||
// }
|
||||
|
||||
// module.exports = {
|
||||
// regexToDfa
|
||||
// };
|
||||
@@ -1,10 +0,0 @@
|
||||
pragma circom 2.0.2;
|
||||
|
||||
include "../../build/compiled.circom";
|
||||
|
||||
component main {
|
||||
public [
|
||||
msg,
|
||||
match_idx
|
||||
]
|
||||
} = Regex(1536, 44, 0);
|
||||
@@ -1,10 +0,0 @@
|
||||
pragma circom 2.0.2;
|
||||
|
||||
include "../../build/compiled.circom";
|
||||
|
||||
component main {
|
||||
public [
|
||||
msg,
|
||||
match_idx
|
||||
]
|
||||
} = Regex(1536, 44, 1);
|
||||
@@ -1,10 +0,0 @@
|
||||
pragma circom 2.0.2;
|
||||
|
||||
include "../../build/compiled.circom";
|
||||
|
||||
component main {
|
||||
public [
|
||||
msg,
|
||||
match_idx
|
||||
]
|
||||
} = Regex(1536, 44, 2);
|
||||
@@ -1,10 +0,0 @@
|
||||
pragma circom 2.0.2;
|
||||
|
||||
include "../../build/compiled.circom";
|
||||
|
||||
component main {
|
||||
public [
|
||||
msg,
|
||||
match_idx
|
||||
]
|
||||
} = Regex(1536, 44, 3);
|
||||
@@ -1,7 +0,0 @@
|
||||
Date: Sat, 24 Dec 2022 07:12:37 +0000
|
||||
from: Twitter <verify@twitter.com>
|
||||
to: test <test@test.com>
|
||||
Subject: Password reset request
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/alternative;
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const {expect} = require('chai');
|
||||
const path = require('path');
|
||||
const circom_tester = require('circom_tester');
|
||||
const generator = require('../compiler/gen');
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
|
||||
describe('regex compiler tests', function () {
|
||||
[
|
||||
[
|
||||
['1=(a|b) (2=(b|c)+ )+d', 0],
|
||||
[
|
||||
[
|
||||
'1 entire match and 1st sub-group match',
|
||||
convertMsg('1=a 2=b 2=bc 2=c d'),
|
||||
0,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(1n);
|
||||
expect(signals.main.group_match_count).to.equal(1n);
|
||||
expect(signals.main.start_idx).to.equal(2n);
|
||||
const expected_reveal = encodeString('a');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
['1=(a|b) (2=(b|c)+ )+d', 1],
|
||||
[
|
||||
[
|
||||
'1 entire match and 1st sub-group match',
|
||||
convertMsg('1=a 2=b 2=bc 2=c d'),
|
||||
0,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(1n);
|
||||
expect(signals.main.group_match_count).to.equal(3n);
|
||||
expect(signals.main.start_idx).to.equal(6n);
|
||||
const expected_reveal = encodeString('b');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'1 entire match and 2nd sub-group match',
|
||||
convertMsg('1=a 2=b 2=bc 2=c d'),
|
||||
1,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(1n);
|
||||
expect(signals.main.group_match_count).to.equal(3n);
|
||||
expect(signals.main.start_idx).to.equal(10n);
|
||||
const expected_reveal = encodeString('bc');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'1 entire match and 3rd sub-group match',
|
||||
convertMsg('1=a 2=b 2=bc 2=c d'),
|
||||
2,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(1n);
|
||||
expect(signals.main.group_match_count).to.equal(3n);
|
||||
expect(signals.main.start_idx).to.equal(15n);
|
||||
const expected_reveal = encodeString('c');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'0 entire match and 2 group matches',
|
||||
convertMsg('1=a 2=b 2=bc 2=e d'),
|
||||
1,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(0n);
|
||||
expect(signals.main.group_match_count).to.equal(2n);
|
||||
}
|
||||
],
|
||||
[
|
||||
'2 entire match and 2nd sub-group match',
|
||||
convertMsg('1=a 2=b 2=bc 2=c da 1=a 2=cb 2=c 2=b dd'),
|
||||
1,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(2n);
|
||||
expect(signals.main.group_match_count).to.equal(6n);
|
||||
expect(signals.main.start_idx).to.equal(10n);
|
||||
const expected_reveal = encodeString('bc');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
// todo TOFIX
|
||||
// [
|
||||
// '1 entire match and 1+ group matches with no trails behind the last group',
|
||||
// convertMsg(`1=a 2=b 2=bc 2=c `),
|
||||
// [`1=(a|b) (2=(b|c)+ )+`, 1, 1],
|
||||
// (signals) => {
|
||||
// for (let i = 0; i < signals.main.states.length; i++) {
|
||||
// console.log(signals.main.states[i][8])
|
||||
// }
|
||||
// expect(signals.main.entire_count).to.equal(1n)
|
||||
// expect(signals.main.group_match_count).to.equal(3n)
|
||||
// expect(signals.main.start_idx).to.equal(10n)
|
||||
// const expected_reveal = 'bc'.split('').map((x) => BigInt(x.charCodeAt(0)))
|
||||
// assert_reveal(signals, expected_reveal);
|
||||
// }
|
||||
// ],
|
||||
]
|
||||
],
|
||||
[
|
||||
['(\r\n|\x80)(to|from):((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9| |_|.|"|@|-)+<)?(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+>?\r\n', 2],
|
||||
[
|
||||
[
|
||||
'from to email header',
|
||||
convertMsg(fs.readFileSync(path.join(__dirname, 'header.fixture.txt'), 'utf8')),
|
||||
0,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(2n);
|
||||
expect(signals.main.group_match_count).to.equal(2n);
|
||||
expect(signals.main.start_idx).to.equal(54n);
|
||||
const expected_reveal = encodeString('verify');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
['dkim-signature:((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)=(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|\\/|:|<|=|>|\\?|@|\\[|\\\\|\\]|^|_|`|{|\\||}|~| |\t|\n' +
|
||||
'|\r|\x0B|\f)+; )+bh=(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\+|\\/|=)+; ', 2],
|
||||
[
|
||||
[
|
||||
'assert body hash',
|
||||
convertMsg('\r\ndkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=twitter.com; s=dkim-201406; t=1671865957; bh=hEMyi6n9V0N6aGtz3lEc6fQBlZRVUok/tkwpRCmrnaa=; h=Date:From:To:Subject:MIME-Version:Content-Type:Message-ID; b='),
|
||||
0,
|
||||
(signals) => {
|
||||
expect(signals.main.entire_count).to.equal(1n);
|
||||
expect(signals.main.group_match_count).to.equal(1n);
|
||||
const expected_reveal = encodeString('hEMyi6n9V0N6aGtz3lEc6fQBlZRVUok/tkwpRCmrnaa=');
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
.forEach((regexSuite) => {
|
||||
const regex = regexSuite[0][0];
|
||||
const group_idx = regexSuite[0][1];
|
||||
const tests = regexSuite[1];
|
||||
|
||||
const testCircomFile = `test_regex_compiler_group_${group_idx}.circom`;
|
||||
let circuit;
|
||||
describe(`/${regex}/ > group idx: ${group_idx} > ${testCircomFile}`, () => {
|
||||
before(async function () {
|
||||
await generator.generateCircuit(
|
||||
regex,
|
||||
'../circuits'
|
||||
);
|
||||
circuit = await wasm_tester(
|
||||
path.join(__dirname, 'circuits', testCircomFile),
|
||||
{recompile: process.env.NO_COMPILE ? false : true, output: `${__dirname}/../build/`, O: 0}
|
||||
);
|
||||
});
|
||||
tests.forEach((test) => {
|
||||
const name = test[0];
|
||||
const content = test[1];
|
||||
const match_idx = test[2];
|
||||
const checkSignals = test[3];
|
||||
|
||||
describe(name, () => {
|
||||
it('checks witness', async function() {
|
||||
let witness = await circuit.calculateWitness({msg: content, match_idx});
|
||||
const signals = await circuit.getJSONOutput('main', witness);
|
||||
checkSignals(signals);
|
||||
await circuit.checkConstraints(witness);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('exceptions', () => {
|
||||
it('character class not supported', async () => {
|
||||
try {
|
||||
await generator.generateCircuit(
|
||||
'[a-z]',
|
||||
'../circuits'
|
||||
);
|
||||
}
|
||||
catch (e) {
|
||||
expect(e.message).to.equal('CharacterClass not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
expect.fail('should have thrown');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function encodeString(str) {
|
||||
return str.split('').map((x) => BigInt(x.charCodeAt(0)));
|
||||
}
|
||||
|
||||
function convertMsg(msg, maxLen = 1536) {
|
||||
let msgEncoded = msg.split('').map((x) => x.charCodeAt(0));
|
||||
while (msgEncoded.length < maxLen) {
|
||||
msgEncoded.push(0);
|
||||
}
|
||||
msgEncoded = msgEncoded.map((x) => `${x}`);
|
||||
return msgEncoded;
|
||||
}
|
||||
|
||||
function assert_reveal(signals, expected_reveal) {
|
||||
for (let m in signals.main.reveal_shifted) {
|
||||
const value = signals.main.reveal_shifted[m];
|
||||
if (expected_reveal[m]) {
|
||||
expect(value).to.equal(expected_reveal[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
const fs = require('fs');
|
||||
import { expect } from 'chai';
|
||||
const path = require('path')
|
||||
const circom_tester = require('circom_tester');
|
||||
const generator = require('../compiler/gen')
|
||||
const wasm_tester = circom_tester.wasm;
|
||||
|
||||
describe("regex compiler tests", function () {
|
||||
[
|
||||
[
|
||||
[`1=(a|b) (2=(b|c)+ )+d`, 0],
|
||||
[
|
||||
[
|
||||
'1 entire match and 1st sub-group match',
|
||||
convertMsg(`1=a 2=b 2=bc 2=c d`),
|
||||
0,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(1n)
|
||||
expect(signals.main.group_match_count).to.equal(1n)
|
||||
expect(signals.main.start_idx).to.equal(2n)
|
||||
const expected_reveal = encodeString('a')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
[`1=(a|b) (2=(b|c)+ )+d`, 1],
|
||||
[
|
||||
[
|
||||
'1 entire match and 1st sub-group match',
|
||||
convertMsg(`1=a 2=b 2=bc 2=c d`),
|
||||
0,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(1n)
|
||||
expect(signals.main.group_match_count).to.equal(3n)
|
||||
expect(signals.main.start_idx).to.equal(6n)
|
||||
const expected_reveal = encodeString('b')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'1 entire match and 2nd sub-group match',
|
||||
convertMsg(`1=a 2=b 2=bc 2=c d`),
|
||||
1,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(1n)
|
||||
expect(signals.main.group_match_count).to.equal(3n)
|
||||
expect(signals.main.start_idx).to.equal(10n)
|
||||
const expected_reveal = encodeString('bc')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'1 entire match and 3rd sub-group match',
|
||||
convertMsg(`1=a 2=b 2=bc 2=c d`),
|
||||
2,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(1n)
|
||||
expect(signals.main.group_match_count).to.equal(3n)
|
||||
expect(signals.main.start_idx).to.equal(15n)
|
||||
const expected_reveal = encodeString('c')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
[
|
||||
'0 entire match and 2 group matches',
|
||||
convertMsg(`1=a 2=b 2=bc 2=e d`),
|
||||
1,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(0n)
|
||||
expect(signals.main.group_match_count).to.equal(2n)
|
||||
}
|
||||
],
|
||||
[
|
||||
'2 entire match and 2nd sub-group match',
|
||||
convertMsg(`1=a 2=b 2=bc 2=c da 1=a 2=cb 2=c 2=b dd`),
|
||||
1,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(2n)
|
||||
expect(signals.main.group_match_count).to.equal(6n)
|
||||
expect(signals.main.start_idx).to.equal(10n)
|
||||
const expected_reveal = encodeString('bc')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
// todo TOFIX
|
||||
// [
|
||||
// '1 entire match and 1+ group matches with no trails behind the last group',
|
||||
// convertMsg(`1=a 2=b 2=bc 2=c `),
|
||||
// [`1=(a|b) (2=(b|c)+ )+`, 1, 1],
|
||||
// (signals: any) => {
|
||||
// for (let i = 0; i < signals.main.states.length; i++) {
|
||||
// console.log(signals.main.states[i][8])
|
||||
// }
|
||||
// expect(signals.main.entire_count).to.equal(1n)
|
||||
// expect(signals.main.group_match_count).to.equal(3n)
|
||||
// expect(signals.main.start_idx).to.equal(10n)
|
||||
// const expected_reveal = 'bc'.split('').map((x: any) => BigInt(x.charCodeAt(0)))
|
||||
// assert_reveal(signals, expected_reveal);
|
||||
// }
|
||||
// ],
|
||||
]
|
||||
],
|
||||
[
|
||||
['(\r\n|\x80)(to|from):((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9| |_|.|"|@|-)+<)?(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|_|.|-)+>?\r\n', 2],
|
||||
[
|
||||
[
|
||||
'from to email header',
|
||||
convertMsg(fs.readFileSync(path.join(__dirname, 'header.fixture.txt'), 'utf8')),
|
||||
0,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(2n)
|
||||
expect(signals.main.group_match_count).to.equal(2n)
|
||||
expect(signals.main.start_idx).to.equal(54n)
|
||||
const expected_reveal = encodeString('verify')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
],
|
||||
]
|
||||
],
|
||||
[
|
||||
['dkim-signature:((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)=(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|!|"|#|$|%|&|\'|\\(|\\)|\\*|\\+|,|-|.|\\/|:|<|=|>|\\?|@|\\[|\\\\|\\]|^|_|`|{|\\||}|~| |\t|\n' +
|
||||
'|\r|\x0B|\f)+; )+bh=(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|0|1|2|3|4|5|6|7|8|9|\\+|\\/|=)+; ', 2],
|
||||
[
|
||||
[
|
||||
'assert body hash',
|
||||
convertMsg("\r\ndkim-signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=twitter.com; s=dkim-201406; t=1671865957; bh=hEMyi6n9V0N6aGtz3lEc6fQBlZRVUok/tkwpRCmrnaa=; h=Date:From:To:Subject:MIME-Version:Content-Type:Message-ID; b="),
|
||||
0,
|
||||
(signals: any) => {
|
||||
expect(signals.main.entire_count).to.equal(1n)
|
||||
expect(signals.main.group_match_count).to.equal(1n)
|
||||
const expected_reveal = encodeString('hEMyi6n9V0N6aGtz3lEc6fQBlZRVUok/tkwpRCmrnaa=')
|
||||
assert_reveal(signals, expected_reveal);
|
||||
}
|
||||
]
|
||||
]
|
||||
],
|
||||
]
|
||||
.forEach((regexSuite: any) => {
|
||||
const regex = regexSuite[0][0]
|
||||
const group_idx = regexSuite[0][1]
|
||||
const tests: any = regexSuite[1]
|
||||
|
||||
const testCircomFile = `test_regex_compiler_group_${group_idx}.circom`
|
||||
let circuit: any;
|
||||
describe(`/${regex}/ > group idx: ${group_idx} > ${testCircomFile}`, () => {
|
||||
before(async function () {
|
||||
await generator.generateCircuit(
|
||||
regex,
|
||||
'../circuits'
|
||||
)
|
||||
circuit = await wasm_tester(
|
||||
path.join(__dirname, "circuits", testCircomFile),
|
||||
{recompile: process.env.NO_COMPILE ? false : true, output: `${__dirname}/../build/`, O: 0}
|
||||
);
|
||||
});
|
||||
tests.forEach((test: any) => {
|
||||
//@ts-ignore
|
||||
const name: string = test[0]
|
||||
//@ts-ignore
|
||||
const content: string = test[1]
|
||||
//@ts-ignore
|
||||
const match_idx: number = test[2]
|
||||
//@ts-ignore
|
||||
const checkSignals: Function = test[3]
|
||||
|
||||
describe(name, () => {
|
||||
it('checks witness', async function() {
|
||||
let witness = await circuit.calculateWitness({msg: content, match_idx});
|
||||
const signals = await circuit.getJSONOutput('main', witness);
|
||||
checkSignals(signals)
|
||||
await circuit.checkConstraints(witness);
|
||||
});
|
||||
});
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe('exceptions', () => {
|
||||
it('character class not supported', async () => {
|
||||
try {
|
||||
await generator.generateCircuit(
|
||||
'[a-z]',
|
||||
'../circuits'
|
||||
)
|
||||
}
|
||||
catch (e: any) {
|
||||
expect(e.message).to.equal('CharacterClass not supported')
|
||||
return
|
||||
}
|
||||
|
||||
expect.fail('should have thrown')
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function encodeString(str: string) {
|
||||
return str.split('').map((x: any) => BigInt(x.charCodeAt(0)));
|
||||
}
|
||||
|
||||
function convertMsg(msg: string, maxLen: number = 1536) {
|
||||
let msgEncoded = msg.split('').map((x: any) => x.charCodeAt(0));
|
||||
while (msgEncoded.length < maxLen) {
|
||||
msgEncoded.push(0);
|
||||
}
|
||||
msgEncoded = msgEncoded.map((x: any) => `${x}`);
|
||||
return msgEncoded;
|
||||
}
|
||||
|
||||
function assert_reveal(signals: any, expected_reveal: bigint[]) {
|
||||
for (let m in signals.main.reveal_shifted) {
|
||||
const value = signals.main.reveal_shifted[m];
|
||||
if (expected_reveal[m as any]) {
|
||||
expect(value).to.equal(expected_reveal[m as any]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user