mirror of
https://github.com/JernKunpittaya/full_zk_regex.git
synced 2026-01-08 21:08:01 -05:00
delete experiment files
This commit is contained in:
@@ -1,648 +0,0 @@
|
||||
// explore space, for writing circom b4 integrating with frontend.
|
||||
import {
|
||||
tagged_simplifyGraph,
|
||||
findMatchStateTagged,
|
||||
formatForCircom,
|
||||
} from "./gen_tagged_dfa";
|
||||
import { reverseDFA } from "./gen_rev_dfa";
|
||||
import { simplifyGraph } from "./gen_dfa";
|
||||
import { M1ToM2 } from "./gen_m2";
|
||||
import { M2ToM3 } from "./gen_m3";
|
||||
import { createM4, registerToState } from "./gen_m4";
|
||||
import { reassignM3M4 } from "./reassign_m3_m4";
|
||||
|
||||
export function explore_gen_circom(regex, submatches) {
|
||||
const tagged_simp_graph = tagged_simplifyGraph(regex, submatches);
|
||||
// console.log("eden aka m1: ", tagged_simp_graph);
|
||||
let m2_graph = M1ToM2(tagged_simp_graph);
|
||||
// console.log("m2 jya: ", m2_graph);
|
||||
let m3_graph = M2ToM3(m2_graph);
|
||||
// console.log("m3 jya: ", m3_graph);
|
||||
let m4_graph = createM4(tagged_simp_graph);
|
||||
let tagged_m4_graph = registerToState(m4_graph);
|
||||
// console.log("tagged m4: ", tagged_m4_graph);
|
||||
let final_m3_m4 = reassignM3M4(m3_graph, tagged_m4_graph);
|
||||
console.log("final m3: ", final_m3_m4["final_m3_graph"]);
|
||||
console.log("final m4: ", final_m3_m4["final_m4_graph"]);
|
||||
// const forw_graph = formatForCircom(final_m3_m4["final_m4_graph"]);
|
||||
// const rev_graph = formatForCircom(final_m3_m4["final_m3_graph"]);
|
||||
// console.log("m4 graph: ", forw_graph);
|
||||
// console.log("m4 rev: ", forw_graph["tags"]);
|
||||
// console.log("nice m3 (rev): ", rev_graph);
|
||||
// lib_head, join with \n
|
||||
let final_text = "";
|
||||
const lib_head = [];
|
||||
lib_head.push("pragma circom 2.1.4;");
|
||||
lib_head.push("");
|
||||
lib_head.push('include "circomlib/circuits/comparators.circom";');
|
||||
lib_head.push('include "circomlib/circuits/gates.circom";');
|
||||
lib_head.push("");
|
||||
// build template MultiOR(n)
|
||||
lib_head.push("template MultiOR(n) {");
|
||||
lib_head.push("\tsignal input in[n];");
|
||||
lib_head.push("\tsignal output out;");
|
||||
lib_head.push("");
|
||||
lib_head.push("\tsignal sums[n];");
|
||||
lib_head.push("\tsums[0] <== in[0];");
|
||||
lib_head.push("\tfor (var i = 1; i < n; i++) {");
|
||||
lib_head.push("\t\tsums[i] <== sums[i-1] + in[i];");
|
||||
lib_head.push("\t}");
|
||||
lib_head.push("\tcomponent is_zero = IsZero();");
|
||||
lib_head.push("\tis_zero.in <== sums[n-1];");
|
||||
lib_head.push("\tout <== 1 - is_zero.out;");
|
||||
lib_head.push("}");
|
||||
lib_head.push("");
|
||||
|
||||
final_text += lib_head.join("\n") + "\n";
|
||||
// build tpl_head, join with \n
|
||||
const tpl_head = [];
|
||||
tpl_head.push("template Regex (msg_bytes, reveal_bytes, group_idx){");
|
||||
tpl_head.push("\tsignal input msg[msg_bytes];");
|
||||
tpl_head.push("\tsignal input match_idx;");
|
||||
tpl_head.push("\tsignal output start_idx;");
|
||||
tpl_head.push("\tsignal output group_match_count;");
|
||||
tpl_head.push("\tsignal output entire_count;");
|
||||
tpl_head.push("");
|
||||
tpl_head.push(
|
||||
"\tsignal reveal_shifted_intermediate[reveal_bytes][msg_bytes];"
|
||||
);
|
||||
tpl_head.push("\tsignal output reveal_shifted[reveal_bytes];");
|
||||
// add adj_reveal (adjusted reveal) to reverse rev_reveal
|
||||
tpl_head.push("\tsignal adj_reveal[msg_bytes];");
|
||||
tpl_head.push("");
|
||||
tpl_head.push("\tsignal in[msg_bytes];");
|
||||
tpl_head.push("\tsignal rev_in[msg_bytes];");
|
||||
tpl_head.push("\tfor (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_head.push("\t\tin[i] <== msg[i];");
|
||||
// backward input msgs
|
||||
tpl_head.push("\t\trev_in[i] <== msg[msg_bytes - i - 1];");
|
||||
tpl_head.push("\t}");
|
||||
|
||||
final_text += tpl_head.join("\n") + "\n";
|
||||
// compile content placeholder, join with \n\t
|
||||
// format tags stuffs
|
||||
let new_tags = {};
|
||||
for (let key in forw_graph["tags"]) {
|
||||
let tran_arr = [];
|
||||
for (let ele of forw_graph["tags"][key]) {
|
||||
tran_arr.push(ele);
|
||||
}
|
||||
new_tags[key] = tran_arr;
|
||||
}
|
||||
const N = forw_graph["states"].length;
|
||||
const accept_states = forw_graph["accepted_states"];
|
||||
|
||||
let eq_i = 0;
|
||||
let lt_i = 0;
|
||||
let and_i = 0;
|
||||
let multi_or_i = 0;
|
||||
|
||||
// rev portion
|
||||
const rev_N = rev_graph["states"].length;
|
||||
const rev_accept_states = rev_graph["accepted_states"];
|
||||
|
||||
let rev_eq_i = 0;
|
||||
let rev_lt_i = 0;
|
||||
let rev_and_i = 0;
|
||||
let rev_multi_or_i = 0;
|
||||
|
||||
let rev_lines = [];
|
||||
rev_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
|
||||
for (let i = 1; i < rev_N; i++) {
|
||||
const rev_outputs = [];
|
||||
for (let [k, prev_i] of rev_graph["rev_transitions"][i]) {
|
||||
let rev_vals = new Set(JSON.parse(k));
|
||||
const rev_eq_outputs = [];
|
||||
|
||||
const rev_uppercase = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
|
||||
const rev_lowercase = new Set("abcdefghijklmnopqrstuvwxyz".split(""));
|
||||
const rev_digits = new Set("0123456789".split(""));
|
||||
|
||||
if (
|
||||
new Set([...rev_uppercase].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_uppercase.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_uppercase.has(x)));
|
||||
rev_lines.push("\t//rev_UPPERCASE");
|
||||
// og
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 64;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
|
||||
// Optimization
|
||||
// rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
// rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== rev_in[i]-64;`);
|
||||
// rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== 27;`);
|
||||
|
||||
// rev_eq_outputs.push(["rev_lt", rev_lt_i]);
|
||||
// rev_lt_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...rev_lowercase].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_lowercase.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_lowercase.has(x)));
|
||||
rev_lines.push("\t//rev_lowercase");
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 96;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...rev_digits].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_digits.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_digits.has(x)));
|
||||
rev_lines.push("\t//digits");
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 47;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
}
|
||||
for (let c of rev_vals) {
|
||||
// assert.strictEqual(c.length, 1);
|
||||
rev_lines.push(`\t//${c}`);
|
||||
rev_lines.push(`\trev_eq[${rev_eq_i}][i] = IsEqual();`);
|
||||
rev_lines.push(`\trev_eq[${rev_eq_i}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(
|
||||
`\trev_eq[${rev_eq_i}][i].in[1] <== ${c.charCodeAt(0)};`
|
||||
);
|
||||
rev_eq_outputs.push(["rev_eq", rev_eq_i]);
|
||||
rev_eq_i += 1;
|
||||
}
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_states[i][${prev_i}];`
|
||||
);
|
||||
|
||||
if (rev_eq_outputs.length === 1) {
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== ${rev_eq_outputs[0][0]}[${rev_eq_outputs[0][1]}][i].out;`
|
||||
);
|
||||
} else if (rev_eq_outputs.length > 1) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i] = MultiOR(${rev_eq_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < rev_eq_outputs.length; output_i++) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i].in[${output_i}] <== ${rev_eq_outputs[output_i][0]}[${rev_eq_outputs[output_i][1]}][i].out;`
|
||||
);
|
||||
}
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_multi_or[${rev_multi_or_i}][i].out;`
|
||||
);
|
||||
rev_multi_or_i += 1;
|
||||
}
|
||||
rev_outputs.push(rev_and_i);
|
||||
rev_and_i += 1;
|
||||
}
|
||||
|
||||
if (rev_outputs.length === 1) {
|
||||
rev_lines.push(
|
||||
`\trev_states[i+1][${i}] <== rev_and[${rev_outputs[0]}][i].out;`
|
||||
);
|
||||
} else if (rev_outputs.length > 1) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i] = MultiOR(${rev_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < rev_outputs.length; output_i++) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i].in[${output_i}] <== rev_and[${rev_outputs[output_i]}][i].out;`
|
||||
);
|
||||
}
|
||||
rev_lines.push(
|
||||
`\trev_states[i+1][${i}] <== rev_multi_or[${rev_multi_or_i}][i].out;`
|
||||
);
|
||||
rev_multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
rev_lines.push("}");
|
||||
// deal with accepted
|
||||
rev_lines.push("component rev_check_accepted[msg_bytes+1];");
|
||||
|
||||
rev_lines.push("for (var i = 0; i <= msg_bytes; i++) {");
|
||||
rev_lines.push(
|
||||
`\trev_check_accepted[i] = MultiOR(${rev_accept_states.size});`
|
||||
);
|
||||
let rev_count_setInd = 0;
|
||||
for (let element of rev_accept_states) {
|
||||
rev_lines.push(
|
||||
`\trev_check_accepted[i].in[${rev_count_setInd}] <== rev_states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
rev_count_setInd++;
|
||||
}
|
||||
|
||||
rev_lines.push("}");
|
||||
|
||||
let rev_declarations = [];
|
||||
|
||||
if (rev_eq_i > 0) {
|
||||
rev_declarations.push(`component rev_eq[${rev_eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_lt_i > 0) {
|
||||
rev_declarations.push(`component rev_lt[${rev_lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_and_i > 0) {
|
||||
rev_declarations.push(`component rev_and[${rev_and_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_multi_or_i > 0) {
|
||||
rev_declarations.push(
|
||||
`component rev_multi_or[${rev_multi_or_i}][msg_bytes];`
|
||||
);
|
||||
}
|
||||
rev_declarations.push(`signal rev_states[msg_bytes+1][${rev_N}];`);
|
||||
rev_declarations.push("");
|
||||
|
||||
let rev_init_code = [];
|
||||
|
||||
rev_init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
rev_init_code.push("\trev_states[i][0] <== 1;");
|
||||
rev_init_code.push("}");
|
||||
|
||||
rev_init_code.push(`for (var i = 1; i < ${rev_N}; i++) {`);
|
||||
rev_init_code.push("\trev_states[0][i] <== 0;");
|
||||
rev_init_code.push("}");
|
||||
|
||||
rev_init_code.push("");
|
||||
|
||||
const rev_reveal_code = [];
|
||||
|
||||
// new_tags region below
|
||||
|
||||
// calculate reveal
|
||||
rev_reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
// TO BE CONTINUED
|
||||
rev_reveal_code.push(
|
||||
"\tadj_reveal[i] <== rev_check_accepted[msg_bytes-i].out;"
|
||||
);
|
||||
rev_reveal_code.push("}");
|
||||
rev_reveal_code.push("");
|
||||
rev_lines = [
|
||||
...rev_declarations,
|
||||
...rev_init_code,
|
||||
...rev_lines,
|
||||
...rev_reveal_code,
|
||||
];
|
||||
|
||||
final_text += "\n\t" + rev_lines.join("\n\t") + "\n";
|
||||
|
||||
let lines = [];
|
||||
lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
|
||||
for (let i = 1; i < N; i++) {
|
||||
const outputs = [];
|
||||
for (let [k, prev_i] of forw_graph["rev_transitions"][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
|
||||
) {
|
||||
console.log("startttt", i);
|
||||
console.log("KK: ", k);
|
||||
console.log("prev: ", prev_i);
|
||||
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;
|
||||
console.log("ENDD");
|
||||
}
|
||||
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[msg_bytes+1];");
|
||||
// deal with accepted
|
||||
lines.push("component check_accepted[msg_bytes+1];");
|
||||
lines.push(`check_accepted[0] = MultiOR(${accept_states.size});`);
|
||||
let count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`check_accepted[0].in[${count_setInd}] <== states[0][${parseInt(
|
||||
element
|
||||
)}];`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(`final_state_sum[0] <== check_accepted[0].out;`);
|
||||
lines.push("for (var i = 1; i <= msg_bytes; i++) {");
|
||||
lines.push(`\tcheck_accepted[i] = MultiOR(${accept_states.size});`);
|
||||
count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`\tcheck_accepted[i].in[${count_setInd}] <== states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(
|
||||
`\tfinal_state_sum[i] <== final_state_sum[i-1] + check_accepted[i].out;`
|
||||
);
|
||||
lines.push("}");
|
||||
lines.push("entire_count <== final_state_sum[msg_bytes];");
|
||||
|
||||
let declarations = [];
|
||||
|
||||
if (eq_i > 0) {
|
||||
declarations.push(`component eq[${eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (lt_i > 0) {
|
||||
declarations.push(`component lt[${lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (and_i > 0) {
|
||||
declarations.push(`component and[${and_i}][msg_bytes];`);
|
||||
}
|
||||
if (multi_or_i > 0) {
|
||||
declarations.push(`component multi_or[${multi_or_i}][msg_bytes];`);
|
||||
}
|
||||
declarations.push(`signal states[msg_bytes+1][${N}];`);
|
||||
declarations.push("");
|
||||
|
||||
let init_code = [];
|
||||
|
||||
init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
init_code.push("\tstates[i][0] <== adj_reveal[i];");
|
||||
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("");
|
||||
|
||||
const reveal_code = [];
|
||||
|
||||
reveal_code.push("signal reveal[msg_bytes];");
|
||||
for (let i = 0; i < Object.keys(new_tags).length; i++) {
|
||||
reveal_code.push(
|
||||
`component and_track${i}[msg_bytes][${new_tags[i].length}];`
|
||||
);
|
||||
}
|
||||
|
||||
reveal_code.push(
|
||||
`component or_track[msg_bytes][${Object.keys(new_tags).length}];`
|
||||
);
|
||||
|
||||
// calculate or_track for all tags
|
||||
reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
|
||||
for (let tagId = 0; tagId < Object.keys(new_tags).length; tagId++) {
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}] = MultiOR(${new_tags[tagId].length});`
|
||||
);
|
||||
for (let tranId = 0; tranId < new_tags[tagId].length; tranId++) {
|
||||
reveal_code.push(`\tand_track${tagId}[i][${tranId}] = AND();`);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].a <== states[i+1][${
|
||||
JSON.parse(new_tags[tagId][tranId])[1]
|
||||
}];`
|
||||
);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].b <== states[i][${
|
||||
JSON.parse(new_tags[tagId][tranId])[0]
|
||||
}];`
|
||||
);
|
||||
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}].in[${tranId}] <== and_track${tagId}[i][${tranId}].out;`
|
||||
);
|
||||
}
|
||||
}
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
// calculate reveal
|
||||
reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
reveal_code.push("\treveal[i] <== in[i] * or_track[i][group_idx].out;");
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
lines = [...declarations, ...init_code, ...lines, ...reveal_code];
|
||||
|
||||
final_text += "\n\t" + lines.join("\n\t") + "\n";
|
||||
|
||||
// tpl_end
|
||||
let tpl_end = [];
|
||||
tpl_end.push("\tvar start_index = 0;");
|
||||
tpl_end.push("var count = 0;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component check_start[msg_bytes + 1];");
|
||||
tpl_end.push("component check_match[msg_bytes + 1];");
|
||||
tpl_end.push("component check_matched_start[msg_bytes + 1];");
|
||||
tpl_end.push("component matched_idx_eq[msg_bytes];");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\tif (i == 0) {");
|
||||
tpl_end.push("\t\tcount += or_track[0][group_idx].out;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("\telse {");
|
||||
tpl_end.push("\t\tcheck_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_start[i].a <== or_track[i][group_idx].out;");
|
||||
tpl_end.push("\t\tcheck_start[i].b <== 1 - or_track[i-1][group_idx].out;");
|
||||
tpl_end.push("\t\tcount += check_start[i].out;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_match[i] = IsEqual();");
|
||||
tpl_end.push("\t\tcheck_match[i].in[0] <== count;");
|
||||
tpl_end.push("\t\tcheck_match[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_matched_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].a <== check_match[i].out;");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].b <== check_start[i].out;");
|
||||
tpl_end.push("\t\tstart_index += check_matched_start[i].out * i;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\tmatched_idx_eq[i] = IsEqual();");
|
||||
tpl_end.push(
|
||||
"\tmatched_idx_eq[i].in[0] <== or_track[i][group_idx].out * count;"
|
||||
);
|
||||
tpl_end.push("\tmatched_idx_eq[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component match_start_idx[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\tmatch_start_idx[i] = IsEqual();");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[0] <== i;");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[1] <== start_index;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("signal reveal_match[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\treveal_match[i] <== matched_idx_eq[i].out * reveal[i];");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var j = 0; j < reveal_bytes; j++) {");
|
||||
tpl_end.push("\treveal_shifted_intermediate[j][j] <== 0;");
|
||||
tpl_end.push("\tfor (var i = j + 1; i < msg_bytes; i++) {");
|
||||
tpl_end.push(
|
||||
"\t\treveal_shifted_intermediate[j][i] <== reveal_shifted_intermediate[j][i - 1] + match_start_idx[i-j].out * reveal_match[i];"
|
||||
);
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push(
|
||||
"\treveal_shifted[j] <== reveal_shifted_intermediate[j][msg_bytes - 1];"
|
||||
);
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("group_match_count <== count;");
|
||||
tpl_end.push("start_idx <== start_index;");
|
||||
final_text += tpl_end.join("\n\t") + "\n}";
|
||||
|
||||
// add main function
|
||||
final_text +=
|
||||
"\n\ncomponent main { public [msg, match_idx] } = Regex(100,44,2);";
|
||||
return final_text;
|
||||
}
|
||||
21
src/explore_graph.js
Normal file
21
src/explore_graph.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// explore space, for writing circom b4 integrating with frontend.
|
||||
import { tagged_simplifyGraph } from "./gen_tagged_dfa";
|
||||
import { M1ToM2 } from "./gen_m2";
|
||||
import { M2ToM3 } from "./gen_m3";
|
||||
import { createM4, registerToState } from "./gen_m4";
|
||||
import { reassignM3M4 } from "./reassign_m3_m4";
|
||||
|
||||
export function explore_graph(regex, submatches) {
|
||||
const tagged_simp_graph = tagged_simplifyGraph(regex, submatches);
|
||||
// console.log("eden aka m1: ", tagged_simp_graph);
|
||||
let m2_graph = M1ToM2(tagged_simp_graph);
|
||||
// console.log("m2 jya: ", m2_graph);
|
||||
let m3_graph = M2ToM3(m2_graph);
|
||||
// console.log("m3 jya: ", m3_graph);
|
||||
let m4_graph = createM4(tagged_simp_graph);
|
||||
let tagged_m4_graph = registerToState(m4_graph);
|
||||
// console.log("tagged m4: ", tagged_m4_graph);
|
||||
let final_m3_m4 = reassignM3M4(m3_graph, tagged_m4_graph);
|
||||
console.log("final m3: ", final_m3_m4["final_m3_graph"]);
|
||||
console.log("final m4: ", final_m3_m4["final_m4_graph"]);
|
||||
}
|
||||
@@ -1,884 +0,0 @@
|
||||
// Assume only 1 regex matched
|
||||
// Show where to start running M4, and corresponding transition for M4
|
||||
import { simplifyGraph } from "./gen_dfa";
|
||||
import { formatForCircom, tagged_simplifyGraph } from "./gen_tagged_dfa";
|
||||
import { M1ToM2 } from "./gen_m2";
|
||||
import { M2ToM3 } from "./gen_m3";
|
||||
import { createM4, registerToState } from "./gen_m4";
|
||||
import { reassignM3M4 } from "./reassign_m3_m4";
|
||||
// generating circom for backward DFA
|
||||
// Step 1: naive gen_forw_circom
|
||||
// Step 2: gen m3
|
||||
// Step 3: gen m4
|
||||
export function gen_all_circom(regex, submatches) {
|
||||
const forw_graph = formatForCircom(simplifyGraph(regex));
|
||||
// lib_head, join with \n
|
||||
let final_text = "";
|
||||
const forw_lib_head = [];
|
||||
forw_lib_head.push("pragma circom 2.1.4;");
|
||||
forw_lib_head.push("");
|
||||
forw_lib_head.push('include "circomlib/circuits/comparators.circom";');
|
||||
forw_lib_head.push('include "circomlib/circuits/gates.circom";');
|
||||
forw_lib_head.push("");
|
||||
// build template MultiOR(n)
|
||||
forw_lib_head.push("template MultiOR(n) {");
|
||||
forw_lib_head.push("\tsignal input in[n];");
|
||||
forw_lib_head.push("\tsignal output out;");
|
||||
forw_lib_head.push("");
|
||||
forw_lib_head.push("\tsignal sums[n];");
|
||||
forw_lib_head.push("\tsums[0] <== in[0];");
|
||||
forw_lib_head.push("\tfor (var i = 1; i < n; i++) {");
|
||||
forw_lib_head.push("\t\tsums[i] <== sums[i-1] + in[i];");
|
||||
forw_lib_head.push("\t}");
|
||||
forw_lib_head.push("\tcomponent is_zero = IsZero();");
|
||||
forw_lib_head.push("\tis_zero.in <== sums[n-1];");
|
||||
forw_lib_head.push("\tout <== 1 - is_zero.out;");
|
||||
forw_lib_head.push("}");
|
||||
forw_lib_head.push("");
|
||||
|
||||
// build tpl_head, join with \n
|
||||
const forw_tpl_head = [];
|
||||
forw_tpl_head.push("template Regex (msg_bytes, reveal_bytes, group_idx){");
|
||||
forw_tpl_head.push("\tsignal input in[msg_bytes];");
|
||||
// og tpl_head start
|
||||
forw_tpl_head.push("\tsignal input match_idx;");
|
||||
forw_tpl_head.push("\tsignal output start_idx;");
|
||||
forw_tpl_head.push("\tsignal output group_match_count;");
|
||||
forw_tpl_head.push("\tsignal output entire_count;");
|
||||
forw_tpl_head.push("");
|
||||
forw_tpl_head.push(
|
||||
"\tsignal reveal_shifted_intermediate[reveal_bytes][msg_bytes];"
|
||||
);
|
||||
forw_tpl_head.push("\tsignal output reveal_shifted[reveal_bytes];");
|
||||
forw_tpl_head.push("");
|
||||
// og tpl_head end
|
||||
// add forw_adj_reveal (adjusted reveal) to mark the matched points for m3 dfa
|
||||
forw_tpl_head.push("\tsignal forw_adj_reveal[msg_bytes];");
|
||||
forw_tpl_head.push("");
|
||||
|
||||
// compile content placeholder, join with \n\t
|
||||
// format tags stuffs
|
||||
const forw_N = forw_graph["states"].size;
|
||||
const forw_accept_states = forw_graph["accepted_states"];
|
||||
|
||||
let forw_eq_i = 0;
|
||||
let forw_lt_i = 0;
|
||||
let forw_and_i = 0;
|
||||
let forw_multi_or_i = 0;
|
||||
|
||||
let forw_lines = [];
|
||||
const uppercase = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
|
||||
const lowercase = new Set("abcdefghijklmnopqrstuvwxyz".split(""));
|
||||
const digits = new Set("0123456789".split(""));
|
||||
forw_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
for (let i = 1; i < forw_N; i++) {
|
||||
const forw_outputs = [];
|
||||
for (let [k, prev_i] of forw_graph["rev_transitions"][i]) {
|
||||
let forw_vals = new Set(JSON.parse(k));
|
||||
const forw_eq_outputs = [];
|
||||
|
||||
if (
|
||||
new Set([...uppercase].filter((x) => forw_vals.has(x))).size ===
|
||||
uppercase.size
|
||||
) {
|
||||
forw_vals = new Set([...forw_vals].filter((x) => !uppercase.has(x)));
|
||||
forw_lines.push("\t//UPPERCASE");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 64;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...lowercase].filter((x) => forw_vals.has(x))).size ===
|
||||
lowercase.size
|
||||
) {
|
||||
forw_vals = new Set([...forw_vals].filter((x) => !lowercase.has(x)));
|
||||
forw_lines.push("\t//lowercase");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 96;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...digits].filter((x) => forw_vals.has(x))).size ===
|
||||
digits.size
|
||||
) {
|
||||
forw_vals = new Set([...forw_vals].filter((x) => !digits.has(x)));
|
||||
forw_lines.push("\t//digits");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 47;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
for (let c of forw_vals) {
|
||||
// to make sure just one alphabet, in backend
|
||||
// assert.strictEqual(c.length, 1);
|
||||
forw_lines.push(`\t//${c}`);
|
||||
forw_lines.push(`\tforw_eq[${forw_eq_i}][i] = IsEqual();`);
|
||||
forw_lines.push(`\tforw_eq[${forw_eq_i}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(
|
||||
`\tforw_eq[${forw_eq_i}][i].in[1] <== ${c.charCodeAt(0)};`
|
||||
);
|
||||
forw_eq_outputs.push(["forw_eq", forw_eq_i]);
|
||||
forw_eq_i += 1;
|
||||
}
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_states[i][${prev_i}];`
|
||||
);
|
||||
|
||||
if (forw_eq_outputs.length === 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== ${forw_eq_outputs[0][0]}[${forw_eq_outputs[0][1]}][i].out;`
|
||||
);
|
||||
} else if (forw_eq_outputs.length > 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i] = MultiOR(${forw_eq_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < forw_eq_outputs.length; output_i++) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i].in[${output_i}] <== ${forw_eq_outputs[output_i][0]}[${forw_eq_outputs[output_i][1]}][i].out;`
|
||||
);
|
||||
}
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_multi_or[${forw_multi_or_i}][i].out;`
|
||||
);
|
||||
forw_multi_or_i += 1;
|
||||
}
|
||||
forw_outputs.push(forw_and_i);
|
||||
forw_and_i += 1;
|
||||
}
|
||||
|
||||
if (forw_outputs.length === 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_states[i+1][${i}] <== forw_and[${forw_outputs[0]}][i].out;`
|
||||
);
|
||||
} else if (forw_outputs.length > 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i] = MultiOR(${forw_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < forw_outputs.length; output_i++) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i].in[${output_i}] <== forw_and[${forw_outputs[output_i]}][i].out;`
|
||||
);
|
||||
}
|
||||
forw_lines.push(
|
||||
`\tforw_states[i+1][${i}] <== forw_multi_or[${forw_multi_or_i}][i].out;`
|
||||
);
|
||||
forw_multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
forw_lines.push("}");
|
||||
// deal with accepted
|
||||
forw_lines.push("component forw_check_accepted[msg_bytes+1];");
|
||||
|
||||
forw_lines.push("for (var i = 0; i <= msg_bytes; i++) {");
|
||||
forw_lines.push(
|
||||
`\tforw_check_accepted[i] = MultiOR(${forw_accept_states.size});`
|
||||
);
|
||||
let forw_count_setInd = 0;
|
||||
for (let element of forw_accept_states) {
|
||||
forw_lines.push(
|
||||
`\tforw_check_accepted[i].in[${forw_count_setInd}] <== forw_states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
forw_count_setInd++;
|
||||
}
|
||||
|
||||
forw_lines.push("}");
|
||||
|
||||
let forw_declarations = [];
|
||||
|
||||
if (forw_eq_i > 0) {
|
||||
forw_declarations.push(`component forw_eq[${forw_eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_lt_i > 0) {
|
||||
forw_declarations.push(`component forw_lt[${forw_lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_and_i > 0) {
|
||||
forw_declarations.push(`component forw_and[${forw_and_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_multi_or_i > 0) {
|
||||
forw_declarations.push(
|
||||
`component forw_multi_or[${forw_multi_or_i}][msg_bytes];`
|
||||
);
|
||||
}
|
||||
forw_declarations.push(`signal forw_states[msg_bytes+1][${forw_N}];`);
|
||||
forw_declarations.push("");
|
||||
|
||||
let forw_init_code = [];
|
||||
|
||||
forw_init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
forw_init_code.push("\tforw_states[i][0] <== 1;");
|
||||
forw_init_code.push("}");
|
||||
|
||||
forw_init_code.push(`for (var i = 1; i < ${forw_N}; i++) {`);
|
||||
forw_init_code.push("\tforw_states[0][i] <== 0;");
|
||||
forw_init_code.push("}");
|
||||
|
||||
forw_init_code.push("");
|
||||
|
||||
const forw_reveal_code = [];
|
||||
|
||||
// new_tags region below
|
||||
|
||||
// calculate reveal
|
||||
forw_reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
// forw_adj_reveal is in reading backwards to be compatible with m3 reverse reading
|
||||
forw_reveal_code.push(
|
||||
"\tforw_adj_reveal[i] <== forw_check_accepted[msg_bytes - i].out;"
|
||||
);
|
||||
forw_reveal_code.push("}");
|
||||
forw_reveal_code.push("");
|
||||
forw_lines = [
|
||||
...forw_declarations,
|
||||
...forw_init_code,
|
||||
...forw_lines,
|
||||
...forw_reveal_code,
|
||||
];
|
||||
|
||||
// add main function
|
||||
|
||||
// return forw_final_text;
|
||||
|
||||
// ========================= step 2 region (m3 region) =============================
|
||||
const tagged_simp_graph = tagged_simplifyGraph(regex, submatches);
|
||||
let m2_graph = M1ToM2(tagged_simp_graph);
|
||||
let m3_graph = M2ToM3(m2_graph);
|
||||
let m4_graph = createM4(tagged_simp_graph);
|
||||
let tagged_m4_graph = registerToState(m4_graph);
|
||||
let final_m3_m4 = reassignM3M4(m3_graph, tagged_m4_graph);
|
||||
const m3_circom_graph = formatForCircom(final_m3_m4["final_m3_graph"]);
|
||||
const m4_circom_graph = formatForCircom(final_m3_m4["final_m4_graph"]);
|
||||
let m3_tpl_head = [];
|
||||
m3_tpl_head.push("\tsignal m3_in[msg_bytes];");
|
||||
m3_tpl_head.push("\tsignal m3_adj_reveal[msg_bytes];");
|
||||
m3_tpl_head.push("\tfor (var i = 0; i < msg_bytes; i++) {");
|
||||
// backward input msgs
|
||||
m3_tpl_head.push("\t\tm3_in[i] <== in[msg_bytes - i - 1];");
|
||||
m3_tpl_head.push("\t}");
|
||||
|
||||
const m3_N = m3_circom_graph["states"].size;
|
||||
const m3_accept_states = m3_circom_graph["accepted_states"];
|
||||
|
||||
let m3_eq_i = 0;
|
||||
let m3_lt_i = 0;
|
||||
let m3_and_i = 0;
|
||||
let m3_multi_or_i = 0;
|
||||
|
||||
let m3_lines = [];
|
||||
m3_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
for (let i = 1; i < m3_N; i++) {
|
||||
const m3_outputs = [];
|
||||
for (let [k, prev_i] of m3_circom_graph["rev_transitions"][i]) {
|
||||
let m3_vals = new Set(JSON.parse(k));
|
||||
const m3_eq_outputs = [];
|
||||
|
||||
if (
|
||||
new Set([...uppercase].filter((x) => m3_vals.has(x))).size ===
|
||||
uppercase.size
|
||||
) {
|
||||
m3_vals = new Set([...m3_vals].filter((x) => !uppercase.has(x)));
|
||||
m3_lines.push("\t//UPPERCASE");
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[0] <== 64;`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[1] <== m3_in[i];`);
|
||||
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[0] <== m3_in[i];`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
m3_lines.push(`\tm3_and[${m3_and_i}][i] = AND();`);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].a <== m3_lt[${m3_lt_i}][i].out;`
|
||||
);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].b <== m3_lt[${m3_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
m3_eq_outputs.push(["m3_and", m3_and_i]);
|
||||
m3_lt_i += 2;
|
||||
m3_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...lowercase].filter((x) => m3_vals.has(x))).size ===
|
||||
lowercase.size
|
||||
) {
|
||||
m3_vals = new Set([...m3_vals].filter((x) => !lowercase.has(x)));
|
||||
m3_lines.push("\t//lowercase");
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[0] <== 96;`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[1] <== m3_in[i];`);
|
||||
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[0] <== m3_in[i];`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
m3_lines.push(`\tm3_and[${m3_and_i}][i] = AND();`);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].a <== m3_lt[${m3_lt_i}][i].out;`
|
||||
);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].b <== m3_lt[${m3_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
m3_eq_outputs.push(["m3_and", m3_and_i]);
|
||||
m3_lt_i += 2;
|
||||
m3_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...digits].filter((x) => m3_vals.has(x))).size === digits.size
|
||||
) {
|
||||
m3_vals = new Set([...m3_vals].filter((x) => !digits.has(x)));
|
||||
m3_lines.push("\t//digits");
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[0] <== 47;`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i}][i].in[1] <== m3_in[i];`);
|
||||
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i] = LessThan(8);`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[0] <== m3_in[i];`);
|
||||
m3_lines.push(`\tm3_lt[${m3_lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
m3_lines.push(`\tm3_and[${m3_and_i}][i] = AND();`);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].a <== m3_lt[${m3_lt_i}][i].out;`
|
||||
);
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].b <== m3_lt[${m3_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
m3_eq_outputs.push(["m3_and", m3_and_i]);
|
||||
m3_lt_i += 2;
|
||||
m3_and_i += 1;
|
||||
}
|
||||
for (let c of m3_vals) {
|
||||
// to make sure just one alphabet (for backend)
|
||||
// assert.strictEqual(c.length, 1);
|
||||
m3_lines.push(`\t//${c}`);
|
||||
m3_lines.push(`\tm3_eq[${m3_eq_i}][i] = IsEqual();`);
|
||||
m3_lines.push(`\tm3_eq[${m3_eq_i}][i].in[0] <== m3_in[i];`);
|
||||
m3_lines.push(`\tm3_eq[${m3_eq_i}][i].in[1] <== ${c.charCodeAt(0)};`);
|
||||
m3_eq_outputs.push(["m3_eq", m3_eq_i]);
|
||||
m3_eq_i += 1;
|
||||
}
|
||||
|
||||
m3_lines.push(`\tm3_and[${m3_and_i}][i] = AND();`);
|
||||
m3_lines.push(`\tm3_and[${m3_and_i}][i].a <== m3_states[i][${prev_i}];`);
|
||||
|
||||
if (m3_eq_outputs.length === 1) {
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].b <== ${m3_eq_outputs[0][0]}[${m3_eq_outputs[0][1]}][i].out;`
|
||||
);
|
||||
} else if (m3_eq_outputs.length > 1) {
|
||||
m3_lines.push(
|
||||
`\tm3_multi_or[${m3_multi_or_i}][i] = MultiOR(${m3_eq_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < m3_eq_outputs.length; output_i++) {
|
||||
m3_lines.push(
|
||||
`\tm3_multi_or[${m3_multi_or_i}][i].in[${output_i}] <== ${m3_eq_outputs[output_i][0]}[${m3_eq_outputs[output_i][1]}][i].out;`
|
||||
);
|
||||
}
|
||||
m3_lines.push(
|
||||
`\tm3_and[${m3_and_i}][i].b <== m3_multi_or[${m3_multi_or_i}][i].out;`
|
||||
);
|
||||
m3_multi_or_i += 1;
|
||||
}
|
||||
m3_outputs.push(m3_and_i);
|
||||
m3_and_i += 1;
|
||||
}
|
||||
|
||||
if (m3_outputs.length === 1) {
|
||||
m3_lines.push(
|
||||
`\tm3_states[i+1][${i}] <== m3_and[${m3_outputs[0]}][i].out;`
|
||||
);
|
||||
} else if (m3_outputs.length > 1) {
|
||||
m3_lines.push(
|
||||
`\tm3_multi_or[${m3_multi_or_i}][i] = MultiOR(${m3_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < m3_outputs.length; output_i++) {
|
||||
m3_lines.push(
|
||||
`\tm3_multi_or[${m3_multi_or_i}][i].in[${output_i}] <== m3_and[${m3_outputs[output_i]}][i].out;`
|
||||
);
|
||||
}
|
||||
m3_lines.push(
|
||||
`\tm3_states[i+1][${i}] <== m3_multi_or[${m3_multi_or_i}][i].out;`
|
||||
);
|
||||
m3_multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
m3_lines.push("}");
|
||||
// deal with m3_states_num
|
||||
let m3_states_num_str = "m3_states_num[msg_bytes - i - 1] <== ";
|
||||
for (let i = 0; i < m3_N; i++) {
|
||||
if (i == m3_N - 1) {
|
||||
m3_states_num_str += ` m3_states[i][${i}]*${i};`;
|
||||
} else {
|
||||
m3_states_num_str += ` m3_states[i][${i}]*${i} +`;
|
||||
}
|
||||
}
|
||||
m3_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
m3_lines.push(`\t${m3_states_num_str}`);
|
||||
m3_lines.push("}");
|
||||
m3_lines.push("");
|
||||
// Legacy: gone since we shift m3_adj_reveal and m3_states_num to the left by 1 to
|
||||
// work with m4 definition of transition
|
||||
// // separate final state num since m3_states[msg_bytes][0] is undefined.
|
||||
// //(make sense or it have no alphabet to transition in dfa, and we dont really want to accept epsilon)
|
||||
// let m3_final_states_num_str = `m3_states_num[0] <== `;
|
||||
// for (let i = 1; i < m3_N; i++) {
|
||||
// if (i == m3_N - 1) {
|
||||
// m3_final_states_num_str += ` m3_states[msg_bytes][${i}]*${i};`;
|
||||
// } else {
|
||||
// m3_final_states_num_str += ` m3_states[msg_bytes][${i}]*${i} +`;
|
||||
// }
|
||||
// }
|
||||
// m3_lines.push(m3_final_states_num_str);
|
||||
// m3_lines.push("");
|
||||
|
||||
// deal with accepted
|
||||
m3_lines.push("component m3_check_accepted[msg_bytes+1];");
|
||||
|
||||
m3_lines.push("for (var i = 0; i <= msg_bytes; i++) {");
|
||||
m3_lines.push(`\tm3_check_accepted[i] = MultiOR(${m3_accept_states.size});`);
|
||||
let m3_count_setInd = 0;
|
||||
for (let element of m3_accept_states) {
|
||||
m3_lines.push(
|
||||
`\tm3_check_accepted[i].in[${m3_count_setInd}] <== m3_states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
m3_count_setInd++;
|
||||
}
|
||||
|
||||
m3_lines.push("}");
|
||||
|
||||
let m3_declarations = [];
|
||||
|
||||
if (m3_eq_i > 0) {
|
||||
m3_declarations.push(`component m3_eq[${m3_eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (m3_lt_i > 0) {
|
||||
m3_declarations.push(`component m3_lt[${m3_lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (m3_and_i > 0) {
|
||||
m3_declarations.push(`component m3_and[${m3_and_i}][msg_bytes];`);
|
||||
}
|
||||
if (m3_multi_or_i > 0) {
|
||||
m3_declarations.push(`component m3_multi_or[${m3_multi_or_i}][msg_bytes];`);
|
||||
}
|
||||
// m3_states[i+1][j] = 1 iff index i makes transition into state j. similar to others
|
||||
m3_declarations.push(`signal m3_states[msg_bytes+1][${m3_N}];`);
|
||||
// m3_states_num[i+1] tells which state alphabet i leads into (unique state since we use forw_adj_reveal)
|
||||
// already reversed from m3 for running m4
|
||||
m3_declarations.push("signal m3_states_num[msg_bytes+1];");
|
||||
m3_declarations.push("");
|
||||
|
||||
let m3_init_code = [];
|
||||
// add forw_adj_reveal to not make there exist different j,k that makes both m3_states[i][j] and m3_states[i][k] = 1 for some i
|
||||
m3_init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
m3_init_code.push("\tm3_states[i][0] <== forw_adj_reveal[i];");
|
||||
m3_init_code.push("}");
|
||||
|
||||
m3_init_code.push(`for (var i = 1; i < ${m3_N}; i++) {`);
|
||||
m3_init_code.push("\tm3_states[0][i] <== 0;");
|
||||
m3_init_code.push("}");
|
||||
|
||||
m3_init_code.push("");
|
||||
|
||||
const m3_reveal_code = [];
|
||||
|
||||
// new_tags region below
|
||||
|
||||
// calculate reveal
|
||||
m3_reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
// adjusted m3_adj_reveal to have starting point for m4
|
||||
m3_reveal_code.push(
|
||||
"\tm3_adj_reveal[i] <== m3_check_accepted[msg_bytes - i - 1].out;"
|
||||
);
|
||||
m3_reveal_code.push("}");
|
||||
m3_reveal_code.push("");
|
||||
m3_lines = [
|
||||
...m3_declarations,
|
||||
...m3_init_code,
|
||||
...m3_lines,
|
||||
...m3_reveal_code,
|
||||
];
|
||||
|
||||
//================================== step 3 (m4 region) ==============================
|
||||
let new_tags = {};
|
||||
for (let key in m4_circom_graph["tags"]) {
|
||||
let tran_arr = [];
|
||||
for (let ele of m4_circom_graph["tags"][key]) {
|
||||
tran_arr.push(ele);
|
||||
}
|
||||
new_tags[key] = tran_arr;
|
||||
}
|
||||
|
||||
const N = m4_circom_graph["states"].size;
|
||||
const accept_states = m4_circom_graph["accepted_states"];
|
||||
|
||||
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 < msg_bytes; i++) {");
|
||||
|
||||
for (let i = 1; i < N; i++) {
|
||||
const outputs = [];
|
||||
for (let [k, prev_i] of m4_circom_graph["rev_transitions"][i]) {
|
||||
let vals = new Set(JSON.parse(k));
|
||||
const eq_outputs = [];
|
||||
|
||||
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] <== m3_states_num[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== m3_states_num[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] <== m3_states_num[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== m3_states_num[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] <== m3_states_num[i];`);
|
||||
|
||||
lines.push(`\tlt[${lt_i + 1}][i] = LessThan(8);`);
|
||||
lines.push(`\tlt[${lt_i + 1}][i].in[0] <== m3_states_num[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) {
|
||||
// In m4 case, c represents state in m3, hence can be larger than just one alphabet
|
||||
// NOOO assert.strictEqual(c.length, 1);
|
||||
|
||||
lines.push(`\t//string compare: ${c}`);
|
||||
lines.push(`\teq[${eq_i}][i] = IsEqual();`);
|
||||
lines.push(`\teq[${eq_i}][i].in[0] <== m3_states_num[i];`);
|
||||
lines.push(`\teq[${eq_i}][i].in[1] <== ${c};`);
|
||||
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[msg_bytes+1];");
|
||||
// deal with accepted
|
||||
lines.push("component check_accepted[msg_bytes+1];");
|
||||
lines.push(`check_accepted[0] = MultiOR(${accept_states.size});`);
|
||||
let count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`check_accepted[0].in[${count_setInd}] <== states[0][${parseInt(
|
||||
element
|
||||
)}];`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(`final_state_sum[0] <== check_accepted[0].out;`);
|
||||
lines.push("for (var i = 1; i <= msg_bytes; i++) {");
|
||||
lines.push(`\tcheck_accepted[i] = MultiOR(${accept_states.size});`);
|
||||
count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`\tcheck_accepted[i].in[${count_setInd}] <== states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(
|
||||
`\tfinal_state_sum[i] <== final_state_sum[i-1] + check_accepted[i].out;`
|
||||
);
|
||||
lines.push("}");
|
||||
lines.push("entire_count <== final_state_sum[msg_bytes];");
|
||||
|
||||
let declarations = [];
|
||||
|
||||
if (eq_i > 0) {
|
||||
declarations.push(`component eq[${eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (lt_i > 0) {
|
||||
declarations.push(`component lt[${lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (and_i > 0) {
|
||||
declarations.push(`component and[${and_i}][msg_bytes];`);
|
||||
}
|
||||
if (multi_or_i > 0) {
|
||||
declarations.push(`component multi_or[${multi_or_i}][msg_bytes];`);
|
||||
}
|
||||
declarations.push(`signal states[msg_bytes+1][${N}];`);
|
||||
declarations.push("");
|
||||
|
||||
let init_code = [];
|
||||
|
||||
init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
init_code.push("\tstates[i][0] <== m3_adj_reveal[i];");
|
||||
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("");
|
||||
|
||||
const reveal_code = [];
|
||||
|
||||
reveal_code.push("signal reveal[msg_bytes];");
|
||||
for (let i = 0; i < Object.keys(new_tags).length; i++) {
|
||||
reveal_code.push(
|
||||
`component and_track${i}[msg_bytes][${new_tags[i].length}];`
|
||||
);
|
||||
}
|
||||
|
||||
reveal_code.push(
|
||||
`component or_track[msg_bytes][${Object.keys(new_tags).length}];`
|
||||
);
|
||||
|
||||
// calculate or_track for all tags
|
||||
reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
|
||||
for (let tagId = 0; tagId < Object.keys(new_tags).length; tagId++) {
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}] = MultiOR(${new_tags[tagId].length});`
|
||||
);
|
||||
for (let tranId = 0; tranId < new_tags[tagId].length; tranId++) {
|
||||
reveal_code.push(`\tand_track${tagId}[i][${tranId}] = AND();`);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].a <== states[i+1][${
|
||||
JSON.parse(new_tags[tagId][tranId])[1]
|
||||
}];`
|
||||
);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].b <== states[i][${
|
||||
JSON.parse(new_tags[tagId][tranId])[0]
|
||||
}];`
|
||||
);
|
||||
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}].in[${tranId}] <== and_track${tagId}[i][${tranId}].out;`
|
||||
);
|
||||
}
|
||||
}
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
// calculate reveal
|
||||
reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
reveal_code.push("\treveal[i] <== in[i] * or_track[i][group_idx].out;");
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
lines = [...declarations, ...init_code, ...lines, ...reveal_code];
|
||||
|
||||
// tpl_end
|
||||
let tpl_end = [];
|
||||
tpl_end.push("\tvar start_index = 0;");
|
||||
tpl_end.push("var count = 0;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component check_start[msg_bytes + 1];");
|
||||
tpl_end.push("component check_match[msg_bytes + 1];");
|
||||
tpl_end.push("component check_matched_start[msg_bytes + 1];");
|
||||
tpl_end.push("component matched_idx_eq[msg_bytes];");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\tif (i == 0) {");
|
||||
tpl_end.push("\t\tcount += or_track[0][group_idx].out;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("\telse {");
|
||||
tpl_end.push("\t\tcheck_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_start[i].a <== or_track[i][group_idx].out;");
|
||||
tpl_end.push("\t\tcheck_start[i].b <== 1 - or_track[i-1][group_idx].out;");
|
||||
tpl_end.push("\t\tcount += check_start[i].out;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_match[i] = IsEqual();");
|
||||
tpl_end.push("\t\tcheck_match[i].in[0] <== count;");
|
||||
tpl_end.push("\t\tcheck_match[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_matched_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].a <== check_match[i].out;");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].b <== check_start[i].out;");
|
||||
tpl_end.push("\t\tstart_index += check_matched_start[i].out * i;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\tmatched_idx_eq[i] = IsEqual();");
|
||||
tpl_end.push(
|
||||
"\tmatched_idx_eq[i].in[0] <== or_track[i][group_idx].out * count;"
|
||||
);
|
||||
tpl_end.push("\tmatched_idx_eq[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component match_start_idx[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\tmatch_start_idx[i] = IsEqual();");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[0] <== i;");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[1] <== start_index;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("signal reveal_match[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\treveal_match[i] <== matched_idx_eq[i].out * reveal[i];");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var j = 0; j < reveal_bytes; j++) {");
|
||||
tpl_end.push("\treveal_shifted_intermediate[j][j] <== 0;");
|
||||
tpl_end.push("\tfor (var i = j + 1; i < msg_bytes; i++) {");
|
||||
tpl_end.push(
|
||||
"\t\treveal_shifted_intermediate[j][i] <== reveal_shifted_intermediate[j][i - 1] + match_start_idx[i-j].out * reveal_match[i];"
|
||||
);
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push(
|
||||
"\treveal_shifted[j] <== reveal_shifted_intermediate[j][msg_bytes - 1];"
|
||||
);
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("group_match_count <== count;");
|
||||
tpl_end.push("start_idx <== start_index;");
|
||||
|
||||
// ============================= final_text aggregation ===========================
|
||||
final_text += forw_lib_head.join("\n") + "\n";
|
||||
final_text += forw_tpl_head.join("\n") + "\n" + m3_tpl_head.join("\n") + "\n";
|
||||
final_text +=
|
||||
"\n\t" +
|
||||
forw_lines.join("\n\t") +
|
||||
"\n\t" +
|
||||
m3_lines.join("\n\t") +
|
||||
"\n\t" +
|
||||
lines.join("\n\t") +
|
||||
"\n" +
|
||||
tpl_end.join("\n\t") +
|
||||
"\n}";
|
||||
final_text +=
|
||||
"\n\ncomponent main { public [in, match_idx] } = Regex(100, 44,2);";
|
||||
return final_text;
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
// generating circom for backward DFA
|
||||
export function gen_back_circom(rev_graph) {
|
||||
// lib_head, join with \n
|
||||
let rev_final_text = "";
|
||||
const rev_lib_head = [];
|
||||
rev_lib_head.push("pragma circom 2.1.4;");
|
||||
rev_lib_head.push("");
|
||||
rev_lib_head.push('include "circomlib/circuits/comparators.circom";');
|
||||
rev_lib_head.push('include "circomlib/circuits/gates.circom";');
|
||||
rev_lib_head.push("");
|
||||
// build template MultiOR(n)
|
||||
rev_lib_head.push("template MultiOR(n) {");
|
||||
rev_lib_head.push("\tsignal input in[n];");
|
||||
rev_lib_head.push("\tsignal output out;");
|
||||
rev_lib_head.push("");
|
||||
rev_lib_head.push("\tsignal sums[n];");
|
||||
rev_lib_head.push("\tsums[0] <== in[0];");
|
||||
rev_lib_head.push("\tfor (var i = 1; i < n; i++) {");
|
||||
rev_lib_head.push("\t\tsums[i] <== sums[i-1] + in[i];");
|
||||
rev_lib_head.push("\t}");
|
||||
rev_lib_head.push("\tcomponent is_zero = IsZero();");
|
||||
rev_lib_head.push("\tis_zero.in <== sums[n-1];");
|
||||
rev_lib_head.push("\tout <== 1 - is_zero.out;");
|
||||
rev_lib_head.push("}");
|
||||
rev_lib_head.push("");
|
||||
|
||||
rev_final_text += rev_lib_head.join("\n") + "\n";
|
||||
// build tpl_head, join with \n
|
||||
const rev_tpl_head = [];
|
||||
rev_tpl_head.push("template rev_Regex (msg_bytes){");
|
||||
rev_tpl_head.push("\tsignal input msg[msg_bytes];");
|
||||
// add adj_reveal (adjusted reveal) to reverse rev_reveal
|
||||
rev_tpl_head.push("\tsignal output adj_reveal[msg_bytes];");
|
||||
rev_tpl_head.push("");
|
||||
rev_tpl_head.push("");
|
||||
rev_tpl_head.push("\tsignal rev_in[msg_bytes];");
|
||||
rev_tpl_head.push("\tfor (var i = 0; i < msg_bytes; i++) {");
|
||||
// backward input msgs
|
||||
rev_tpl_head.push("\t\trev_in[i] <== msg[msg_bytes - i - 1];");
|
||||
rev_tpl_head.push("\t}");
|
||||
|
||||
rev_final_text += rev_tpl_head.join("\n") + "\n";
|
||||
// compile content placeholder, join with \n\t
|
||||
// format tags stuffs
|
||||
const rev_N = rev_graph["states"].length;
|
||||
const rev_accept_states = rev_graph["accepted_states"];
|
||||
|
||||
let rev_eq_i = 0;
|
||||
let rev_lt_i = 0;
|
||||
let rev_and_i = 0;
|
||||
let rev_multi_or_i = 0;
|
||||
|
||||
let rev_lines = [];
|
||||
rev_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
|
||||
for (let i = 1; i < rev_N; i++) {
|
||||
const rev_outputs = [];
|
||||
for (let [k, prev_i] of rev_graph["rev_transitions"][i]) {
|
||||
let rev_vals = new Set(JSON.parse(k));
|
||||
const rev_eq_outputs = [];
|
||||
|
||||
const rev_uppercase = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
|
||||
const rev_lowercase = new Set("abcdefghijklmnopqrstuvwxyz".split(""));
|
||||
const rev_digits = new Set("0123456789".split(""));
|
||||
|
||||
if (
|
||||
new Set([...rev_uppercase].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_uppercase.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_uppercase.has(x)));
|
||||
rev_lines.push("\t//UPPERCASE");
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 64;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...rev_lowercase].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_lowercase.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_lowercase.has(x)));
|
||||
rev_lines.push("\t//lowercase");
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 96;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...rev_digits].filter((x) => rev_vals.has(x))).size ===
|
||||
rev_digits.size
|
||||
) {
|
||||
rev_vals = new Set([...rev_vals].filter((x) => !rev_digits.has(x)));
|
||||
rev_lines.push("\t//digits");
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[0] <== 47;`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i}][i].in[1] <== rev_in[i];`);
|
||||
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i] = LessThan(8);`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(`\trev_lt[${rev_lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_lt[${rev_lt_i}][i].out;`
|
||||
);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_lt[${rev_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
rev_eq_outputs.push(["rev_and", rev_and_i]);
|
||||
rev_lt_i += 2;
|
||||
rev_and_i += 1;
|
||||
}
|
||||
for (let c of rev_vals) {
|
||||
// assert.strictEqual(c.length, 1);
|
||||
rev_lines.push(`\t//${c}`);
|
||||
rev_lines.push(`\trev_eq[${rev_eq_i}][i] = IsEqual();`);
|
||||
rev_lines.push(`\trev_eq[${rev_eq_i}][i].in[0] <== rev_in[i];`);
|
||||
rev_lines.push(
|
||||
`\trev_eq[${rev_eq_i}][i].in[1] <== ${c.charCodeAt(0)};`
|
||||
);
|
||||
rev_eq_outputs.push(["rev_eq", rev_eq_i]);
|
||||
rev_eq_i += 1;
|
||||
}
|
||||
|
||||
rev_lines.push(`\trev_and[${rev_and_i}][i] = AND();`);
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].a <== rev_states[i][${prev_i}];`
|
||||
);
|
||||
|
||||
if (rev_eq_outputs.length === 1) {
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== ${rev_eq_outputs[0][0]}[${rev_eq_outputs[0][1]}][i].out;`
|
||||
);
|
||||
} else if (rev_eq_outputs.length > 1) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i] = MultiOR(${rev_eq_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < rev_eq_outputs.length; output_i++) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i].in[${output_i}] <== ${rev_eq_outputs[output_i][0]}[${rev_eq_outputs[output_i][1]}][i].out;`
|
||||
);
|
||||
}
|
||||
rev_lines.push(
|
||||
`\trev_and[${rev_and_i}][i].b <== rev_multi_or[${rev_multi_or_i}][i].out;`
|
||||
);
|
||||
rev_multi_or_i += 1;
|
||||
}
|
||||
rev_outputs.push(rev_and_i);
|
||||
rev_and_i += 1;
|
||||
}
|
||||
|
||||
if (rev_outputs.length === 1) {
|
||||
rev_lines.push(
|
||||
`\trev_states[i+1][${i}] <== rev_and[${rev_outputs[0]}][i].out;`
|
||||
);
|
||||
} else if (rev_outputs.length > 1) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i] = MultiOR(${rev_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < rev_outputs.length; output_i++) {
|
||||
rev_lines.push(
|
||||
`\trev_multi_or[${rev_multi_or_i}][i].in[${output_i}] <== rev_and[${rev_outputs[output_i]}][i].out;`
|
||||
);
|
||||
}
|
||||
rev_lines.push(
|
||||
`\trev_states[i+1][${i}] <== rev_multi_or[${rev_multi_or_i}][i].out;`
|
||||
);
|
||||
rev_multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
rev_lines.push("}");
|
||||
// deal with accepted
|
||||
rev_lines.push("component rev_check_accepted[msg_bytes+1];");
|
||||
|
||||
rev_lines.push("for (var i = 0; i <= msg_bytes; i++) {");
|
||||
rev_lines.push(
|
||||
`\trev_check_accepted[i] = MultiOR(${rev_accept_states.size});`
|
||||
);
|
||||
let rev_count_setInd = 0;
|
||||
for (let element of rev_accept_states) {
|
||||
rev_lines.push(
|
||||
`\trev_check_accepted[i].in[${rev_count_setInd}] <== rev_states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
rev_count_setInd++;
|
||||
}
|
||||
|
||||
rev_lines.push("}");
|
||||
|
||||
let rev_declarations = [];
|
||||
|
||||
if (rev_eq_i > 0) {
|
||||
rev_declarations.push(`component rev_eq[${rev_eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_lt_i > 0) {
|
||||
rev_declarations.push(`component rev_lt[${rev_lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_and_i > 0) {
|
||||
rev_declarations.push(`component rev_and[${rev_and_i}][msg_bytes];`);
|
||||
}
|
||||
if (rev_multi_or_i > 0) {
|
||||
rev_declarations.push(
|
||||
`component rev_multi_or[${rev_multi_or_i}][msg_bytes];`
|
||||
);
|
||||
}
|
||||
rev_declarations.push(`signal rev_states[msg_bytes+1][${rev_N}];`);
|
||||
rev_declarations.push("");
|
||||
|
||||
let rev_init_code = [];
|
||||
|
||||
rev_init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
rev_init_code.push("\trev_states[i][0] <== 1;");
|
||||
rev_init_code.push("}");
|
||||
|
||||
rev_init_code.push(`for (var i = 1; i < ${rev_N}; i++) {`);
|
||||
rev_init_code.push("\trev_states[0][i] <== 0;");
|
||||
rev_init_code.push("}");
|
||||
|
||||
rev_init_code.push("");
|
||||
|
||||
const rev_reveal_code = [];
|
||||
|
||||
// new_tags region below
|
||||
|
||||
// calculate reveal
|
||||
rev_reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
// TO BE CONTINUED
|
||||
rev_reveal_code.push(
|
||||
"\tadj_reveal[i] <== rev_check_accepted[msg_bytes-i].out;"
|
||||
);
|
||||
rev_reveal_code.push("}");
|
||||
rev_reveal_code.push("");
|
||||
rev_lines = [
|
||||
...rev_declarations,
|
||||
...rev_init_code,
|
||||
...rev_lines,
|
||||
...rev_reveal_code,
|
||||
];
|
||||
|
||||
rev_final_text += "\n\t" + rev_lines.join("\n\t") + "\n}";
|
||||
|
||||
// add main function
|
||||
rev_final_text += "\n\ncomponent main { public [msg] } = rev_Regex(100);";
|
||||
return rev_final_text;
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
// gen_forw_circom as step 1 in 3 steps
|
||||
import { simplifyGraph } from "./gen_dfa";
|
||||
import { formatForCircom } from "./gen_tagged_dfa";
|
||||
// generating circom for backward DFA
|
||||
// Step 1: naive gen_forw_circom
|
||||
// Step 2: gen m3
|
||||
// Step 3: gen m4
|
||||
export function gen_forw_circom(regex) {
|
||||
const forw_graph = formatForCircom(simplifyGraph(regex));
|
||||
// lib_head, join with \n
|
||||
let forw_final_text = "";
|
||||
const forw_lib_head = [];
|
||||
forw_lib_head.push("pragma circom 2.1.4;");
|
||||
forw_lib_head.push("");
|
||||
forw_lib_head.push('include "circomlib/circuits/comparators.circom";');
|
||||
forw_lib_head.push('include "circomlib/circuits/gates.circom";');
|
||||
forw_lib_head.push("");
|
||||
// build template MultiOR(n)
|
||||
forw_lib_head.push("template MultiOR(n) {");
|
||||
forw_lib_head.push("\tsignal input in[n];");
|
||||
forw_lib_head.push("\tsignal output out;");
|
||||
forw_lib_head.push("");
|
||||
forw_lib_head.push("\tsignal sums[n];");
|
||||
forw_lib_head.push("\tsums[0] <== in[0];");
|
||||
forw_lib_head.push("\tfor (var i = 1; i < n; i++) {");
|
||||
forw_lib_head.push("\t\tsums[i] <== sums[i-1] + in[i];");
|
||||
forw_lib_head.push("\t}");
|
||||
forw_lib_head.push("\tcomponent is_zero = IsZero();");
|
||||
forw_lib_head.push("\tis_zero.in <== sums[n-1];");
|
||||
forw_lib_head.push("\tout <== 1 - is_zero.out;");
|
||||
forw_lib_head.push("}");
|
||||
forw_lib_head.push("");
|
||||
|
||||
forw_final_text += forw_lib_head.join("\n") + "\n";
|
||||
// build tpl_head, join with \n
|
||||
const forw_tpl_head = [];
|
||||
forw_tpl_head.push("template forw_Regex (msg_bytes){");
|
||||
forw_tpl_head.push("\tsignal input in[msg_bytes];");
|
||||
// add adj_reveal (adjusted reveal) to reverse forw_reveal
|
||||
forw_tpl_head.push("\tsignal output adj_reveal[msg_bytes];");
|
||||
forw_tpl_head.push("");
|
||||
forw_tpl_head.push("");
|
||||
|
||||
forw_final_text += forw_tpl_head.join("\n") + "\n";
|
||||
// compile content placeholder, join with \n\t
|
||||
// format tags stuffs
|
||||
const forw_N = forw_graph["states"].size;
|
||||
const forw_accept_states = forw_graph["accepted_states"];
|
||||
|
||||
let forw_eq_i = 0;
|
||||
let forw_lt_i = 0;
|
||||
let forw_and_i = 0;
|
||||
let forw_multi_or_i = 0;
|
||||
|
||||
let forw_lines = [];
|
||||
forw_lines.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
for (let i = 1; i < forw_N; i++) {
|
||||
const forw_outputs = [];
|
||||
for (let [k, prev_i] of forw_graph["rev_transitions"][i]) {
|
||||
let forw_vals = new Set(JSON.parse(k));
|
||||
const forw_eq_outputs = [];
|
||||
|
||||
const forw_uppercase = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""));
|
||||
const forw_lowercase = new Set("abcdefghijklmnopqrstuvwxyz".split(""));
|
||||
const forw_digits = new Set("0123456789".split(""));
|
||||
|
||||
if (
|
||||
new Set([...forw_uppercase].filter((x) => forw_vals.has(x))).size ===
|
||||
forw_uppercase.size
|
||||
) {
|
||||
forw_vals = new Set(
|
||||
[...forw_vals].filter((x) => !forw_uppercase.has(x))
|
||||
);
|
||||
forw_lines.push("\t//UPPERCASE");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 64;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 91;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...forw_lowercase].filter((x) => forw_vals.has(x))).size ===
|
||||
forw_lowercase.size
|
||||
) {
|
||||
forw_vals = new Set(
|
||||
[...forw_vals].filter((x) => !forw_lowercase.has(x))
|
||||
);
|
||||
forw_lines.push("\t//lowercase");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 96;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 123;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
if (
|
||||
new Set([...forw_digits].filter((x) => forw_vals.has(x))).size ===
|
||||
forw_digits.size
|
||||
) {
|
||||
forw_vals = new Set([...forw_vals].filter((x) => !forw_digits.has(x)));
|
||||
forw_lines.push("\t//digits");
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[0] <== 47;`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i}][i].in[1] <== in[i];`);
|
||||
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i] = LessThan(8);`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(`\tforw_lt[${forw_lt_i + 1}][i].in[1] <== 58;`);
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_lt[${forw_lt_i}][i].out;`
|
||||
);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_lt[${forw_lt_i + 1}][i].out;`
|
||||
);
|
||||
|
||||
forw_eq_outputs.push(["forw_and", forw_and_i]);
|
||||
forw_lt_i += 2;
|
||||
forw_and_i += 1;
|
||||
}
|
||||
for (let c of forw_vals) {
|
||||
// assert.strictEqual(c.length, 1);
|
||||
forw_lines.push(`\t//${c}`);
|
||||
forw_lines.push(`\tforw_eq[${forw_eq_i}][i] = IsEqual();`);
|
||||
forw_lines.push(`\tforw_eq[${forw_eq_i}][i].in[0] <== in[i];`);
|
||||
forw_lines.push(
|
||||
`\tforw_eq[${forw_eq_i}][i].in[1] <== ${c.charCodeAt(0)};`
|
||||
);
|
||||
forw_eq_outputs.push(["forw_eq", forw_eq_i]);
|
||||
forw_eq_i += 1;
|
||||
}
|
||||
|
||||
forw_lines.push(`\tforw_and[${forw_and_i}][i] = AND();`);
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].a <== forw_states[i][${prev_i}];`
|
||||
);
|
||||
|
||||
if (forw_eq_outputs.length === 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== ${forw_eq_outputs[0][0]}[${forw_eq_outputs[0][1]}][i].out;`
|
||||
);
|
||||
} else if (forw_eq_outputs.length > 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i] = MultiOR(${forw_eq_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < forw_eq_outputs.length; output_i++) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i].in[${output_i}] <== ${forw_eq_outputs[output_i][0]}[${forw_eq_outputs[output_i][1]}][i].out;`
|
||||
);
|
||||
}
|
||||
forw_lines.push(
|
||||
`\tforw_and[${forw_and_i}][i].b <== forw_multi_or[${forw_multi_or_i}][i].out;`
|
||||
);
|
||||
forw_multi_or_i += 1;
|
||||
}
|
||||
forw_outputs.push(forw_and_i);
|
||||
forw_and_i += 1;
|
||||
}
|
||||
|
||||
if (forw_outputs.length === 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_states[i+1][${i}] <== forw_and[${forw_outputs[0]}][i].out;`
|
||||
);
|
||||
} else if (forw_outputs.length > 1) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i] = MultiOR(${forw_outputs.length});`
|
||||
);
|
||||
for (let output_i = 0; output_i < forw_outputs.length; output_i++) {
|
||||
forw_lines.push(
|
||||
`\tforw_multi_or[${forw_multi_or_i}][i].in[${output_i}] <== forw_and[${forw_outputs[output_i]}][i].out;`
|
||||
);
|
||||
}
|
||||
forw_lines.push(
|
||||
`\tforw_states[i+1][${i}] <== forw_multi_or[${forw_multi_or_i}][i].out;`
|
||||
);
|
||||
forw_multi_or_i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
forw_lines.push("}");
|
||||
// deal with accepted
|
||||
forw_lines.push("component forw_check_accepted[msg_bytes+1];");
|
||||
|
||||
forw_lines.push("for (var i = 0; i <= msg_bytes; i++) {");
|
||||
forw_lines.push(
|
||||
`\tforw_check_accepted[i] = MultiOR(${forw_accept_states.size});`
|
||||
);
|
||||
let forw_count_setInd = 0;
|
||||
for (let element of forw_accept_states) {
|
||||
forw_lines.push(
|
||||
`\tforw_check_accepted[i].in[${forw_count_setInd}] <== forw_states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
forw_count_setInd++;
|
||||
}
|
||||
|
||||
forw_lines.push("}");
|
||||
|
||||
let forw_declarations = [];
|
||||
|
||||
if (forw_eq_i > 0) {
|
||||
forw_declarations.push(`component forw_eq[${forw_eq_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_lt_i > 0) {
|
||||
forw_declarations.push(`component forw_lt[${forw_lt_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_and_i > 0) {
|
||||
forw_declarations.push(`component forw_and[${forw_and_i}][msg_bytes];`);
|
||||
}
|
||||
if (forw_multi_or_i > 0) {
|
||||
forw_declarations.push(
|
||||
`component forw_multi_or[${forw_multi_or_i}][msg_bytes];`
|
||||
);
|
||||
}
|
||||
forw_declarations.push(`signal forw_states[msg_bytes+1][${forw_N}];`);
|
||||
forw_declarations.push("");
|
||||
|
||||
let forw_init_code = [];
|
||||
|
||||
forw_init_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
forw_init_code.push("\tforw_states[i][0] <== 1;");
|
||||
forw_init_code.push("}");
|
||||
|
||||
forw_init_code.push(`for (var i = 1; i < ${forw_N}; i++) {`);
|
||||
forw_init_code.push("\tforw_states[0][i] <== 0;");
|
||||
forw_init_code.push("}");
|
||||
|
||||
forw_init_code.push("");
|
||||
|
||||
const forw_reveal_code = [];
|
||||
|
||||
// new_tags region below
|
||||
|
||||
// calculate reveal
|
||||
forw_reveal_code.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
// TO BE CONTINUED
|
||||
forw_reveal_code.push("\tadj_reveal[i] <== forw_check_accepted[i].out;");
|
||||
forw_reveal_code.push("}");
|
||||
forw_reveal_code.push("");
|
||||
forw_lines = [
|
||||
...forw_declarations,
|
||||
...forw_init_code,
|
||||
...forw_lines,
|
||||
...forw_reveal_code,
|
||||
];
|
||||
|
||||
forw_final_text += "\n\t" + forw_lines.join("\n\t") + "\n}";
|
||||
|
||||
// add main function
|
||||
forw_final_text += "\n\ncomponent main { public [in] } = forw_Regex(100);";
|
||||
return forw_final_text;
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
export function gen_full_circom(final_graph, rev_tran) {
|
||||
// lib_head, join with \n
|
||||
let final_text = "";
|
||||
const lib_head = [];
|
||||
lib_head.push("pragma circom 2.1.4;");
|
||||
lib_head.push("");
|
||||
lib_head.push('include "circomlib/circuits/comparators.circom";');
|
||||
lib_head.push('include "circomlib/circuits/gates.circom";');
|
||||
lib_head.push("");
|
||||
// build template MultiOR(n)
|
||||
lib_head.push("template MultiOR(n) {");
|
||||
lib_head.push("\tsignal input in[n];");
|
||||
lib_head.push("\tsignal output out;");
|
||||
lib_head.push("");
|
||||
lib_head.push("\tsignal sums[n];");
|
||||
lib_head.push("\tsums[0] <== in[0];");
|
||||
lib_head.push("\tfor (var i = 1; i < n; i++) {");
|
||||
lib_head.push("\t\tsums[i] <== sums[i-1] + in[i];");
|
||||
lib_head.push("\t}");
|
||||
lib_head.push("\tcomponent is_zero = IsZero();");
|
||||
lib_head.push("\tis_zero.in <== sums[n-1];");
|
||||
lib_head.push("\tout <== 1 - is_zero.out;");
|
||||
lib_head.push("}");
|
||||
lib_head.push("");
|
||||
|
||||
final_text += lib_head.join("\n") + "\n";
|
||||
// build tpl_head, join with \n
|
||||
const tpl_head = [];
|
||||
tpl_head.push("template Regex (msg_bytes, reveal_bytes, group_idx){");
|
||||
tpl_head.push("\tsignal input msg[msg_bytes];");
|
||||
tpl_head.push("\tsignal input match_idx;");
|
||||
tpl_head.push("\tsignal output start_idx;");
|
||||
tpl_head.push("\tsignal output group_match_count;");
|
||||
tpl_head.push("\tsignal output entire_count;");
|
||||
tpl_head.push("");
|
||||
tpl_head.push(
|
||||
"\tsignal reveal_shifted_intermediate[reveal_bytes][msg_bytes];"
|
||||
);
|
||||
tpl_head.push("\tsignal output reveal_shifted[reveal_bytes];");
|
||||
tpl_head.push("");
|
||||
tpl_head.push("\tvar num_bytes = msg_bytes;");
|
||||
tpl_head.push("\tsignal in[num_bytes];");
|
||||
tpl_head.push("\tfor (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_head.push("\t\tin[i] <== msg[i];");
|
||||
tpl_head.push("\t}");
|
||||
|
||||
final_text += tpl_head.join("\n") + "\n";
|
||||
// compile content placeholder, join with \n\t
|
||||
// format tags stuffs
|
||||
let new_tags = {};
|
||||
for (let key in final_graph["tags"]) {
|
||||
let tran_arr = [];
|
||||
for (let ele of final_graph["tags"][key]) {
|
||||
tran_arr.push(ele);
|
||||
}
|
||||
new_tags[key] = tran_arr;
|
||||
}
|
||||
const N = final_graph["states"].length;
|
||||
const accept_states = final_graph["accepted_states"];
|
||||
|
||||
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++) {");
|
||||
|
||||
for (let i = 1; i < N; i++) {
|
||||
const outputs = [];
|
||||
for (let [k, prev_i] of rev_tran[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];");
|
||||
// deal with accepted
|
||||
lines.push("component check_accepted[num_bytes+1];");
|
||||
lines.push(`check_accepted[0] = MultiOR(${accept_states.size});`);
|
||||
let count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`check_accepted[0].in[${count_setInd}] <== states[0][${parseInt(
|
||||
element
|
||||
)}];`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(`final_state_sum[0] <== check_accepted[0].out;`);
|
||||
lines.push("for (var i = 1; i <= num_bytes; i++) {");
|
||||
lines.push(`\tcheck_accepted[i] = MultiOR(${accept_states.size});`);
|
||||
count_setInd = 0;
|
||||
for (let element of accept_states) {
|
||||
lines.push(
|
||||
`\tcheck_accepted[i].in[${count_setInd}] <== states[i][${parseInt(
|
||||
element
|
||||
)}] ;`
|
||||
);
|
||||
count_setInd++;
|
||||
}
|
||||
lines.push(
|
||||
`\tfinal_state_sum[i] <== final_state_sum[i-1] + check_accepted[i].out;`
|
||||
);
|
||||
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("");
|
||||
|
||||
const reveal_code = [];
|
||||
|
||||
reveal_code.push("signal reveal[num_bytes];");
|
||||
for (let i = 0; i < Object.keys(new_tags).length; i++) {
|
||||
reveal_code.push(
|
||||
`component and_track${i}[num_bytes][${new_tags[i].length}];`
|
||||
);
|
||||
}
|
||||
|
||||
reveal_code.push(
|
||||
`component or_track[num_bytes][${Object.keys(new_tags).length}];`
|
||||
);
|
||||
|
||||
// calculate or_track for all tags
|
||||
reveal_code.push("for (var i = 0; i < num_bytes; i++) {");
|
||||
|
||||
for (let tagId = 0; tagId < Object.keys(new_tags).length; tagId++) {
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}] = MultiOR(${new_tags[tagId].length});`
|
||||
);
|
||||
for (let tranId = 0; tranId < new_tags[tagId].length; tranId++) {
|
||||
reveal_code.push(`\tand_track${tagId}[i][${tranId}] = AND();`);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].a <== states[i+1][${
|
||||
JSON.parse(new_tags[tagId][tranId])[1]
|
||||
}];`
|
||||
);
|
||||
reveal_code.push(
|
||||
`\tand_track${tagId}[i][${tranId}].b <== states[i][${
|
||||
JSON.parse(new_tags[tagId][tranId])[0]
|
||||
}];`
|
||||
);
|
||||
|
||||
reveal_code.push(
|
||||
`\tor_track[i][${tagId}].in[${tranId}] <== and_track${tagId}[i][${tranId}].out;`
|
||||
);
|
||||
}
|
||||
}
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
// calculate reveal
|
||||
reveal_code.push("for (var i = 0; i < num_bytes; i++) {");
|
||||
reveal_code.push("\treveal[i] <== in[i] * or_track[i][group_idx].out;");
|
||||
reveal_code.push("}");
|
||||
reveal_code.push("");
|
||||
lines = [...declarations, ...init_code, ...lines, ...reveal_code];
|
||||
|
||||
final_text += "\n\t" + lines.join("\n\t") + "\n";
|
||||
|
||||
// tpl_end
|
||||
let tpl_end = [];
|
||||
tpl_end.push("\tvar start_index = 0;");
|
||||
tpl_end.push("var count = 0;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component check_start[num_bytes + 1];");
|
||||
tpl_end.push("component check_match[num_bytes + 1];");
|
||||
tpl_end.push("component check_matched_start[num_bytes + 1];");
|
||||
tpl_end.push("component matched_idx_eq[msg_bytes];");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var i = 0; i < num_bytes; i++) {");
|
||||
tpl_end.push("\tif (i == 0) {");
|
||||
tpl_end.push("\t\tcount += or_track[0][group_idx].out;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("\telse {");
|
||||
tpl_end.push("\t\tcheck_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_start[i].a <== or_track[i][group_idx].out;");
|
||||
tpl_end.push("\t\tcheck_start[i].b <== 1 - or_track[i-1][group_idx].out;");
|
||||
tpl_end.push("\t\tcount += check_start[i].out;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_match[i] = IsEqual();");
|
||||
tpl_end.push("\t\tcheck_match[i].in[0] <== count;");
|
||||
tpl_end.push("\t\tcheck_match[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\t\tcheck_matched_start[i] = AND();");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].a <== check_match[i].out;");
|
||||
tpl_end.push("\t\tcheck_matched_start[i].b <== check_start[i].out;");
|
||||
tpl_end.push("\t\tstart_index += check_matched_start[i].out * i;");
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("\tmatched_idx_eq[i] = IsEqual();");
|
||||
tpl_end.push(
|
||||
"\tmatched_idx_eq[i].in[0] <== or_track[i][group_idx].out * count;"
|
||||
);
|
||||
tpl_end.push("\tmatched_idx_eq[i].in[1] <== match_idx + 1;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("component match_start_idx[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\tmatch_start_idx[i] = IsEqual();");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[0] <== i;");
|
||||
tpl_end.push("\tmatch_start_idx[i].in[1] <== start_index;");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("signal reveal_match[msg_bytes];");
|
||||
tpl_end.push("for (var i = 0; i < msg_bytes; i++) {");
|
||||
tpl_end.push("\treveal_match[i] <== matched_idx_eq[i].out * reveal[i];");
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("for (var j = 0; j < reveal_bytes; j++) {");
|
||||
tpl_end.push("\treveal_shifted_intermediate[j][j] <== 0;");
|
||||
tpl_end.push("\tfor (var i = j + 1; i < msg_bytes; i++) {");
|
||||
tpl_end.push(
|
||||
"\t\treveal_shifted_intermediate[j][i] <== reveal_shifted_intermediate[j][i - 1] + match_start_idx[i-j].out * reveal_match[i];"
|
||||
);
|
||||
tpl_end.push("\t}");
|
||||
tpl_end.push(
|
||||
"\treveal_shifted[j] <== reveal_shifted_intermediate[j][msg_bytes - 1];"
|
||||
);
|
||||
tpl_end.push("}");
|
||||
tpl_end.push("");
|
||||
tpl_end.push("group_match_count <== count;");
|
||||
tpl_end.push("start_idx <== start_index;");
|
||||
final_text += tpl_end.join("\n\t") + "\n}";
|
||||
|
||||
// add main function
|
||||
final_text +=
|
||||
"\n\ncomponent main { public [msg, match_idx] } = Regex(1536,44,2);";
|
||||
return final_text;
|
||||
}
|
||||
// module.exports = { gen_circom };
|
||||
@@ -35,7 +35,7 @@ function findAllPathsBetw(m1_graph, start, end) {
|
||||
export function createM4(m1_graph) {
|
||||
let m2_graph = M1ToM2(m1_graph);
|
||||
let m3_graph = M2ToM3(m2_graph);
|
||||
console.log("m3 jyaa: ", m3_graph);
|
||||
// console.log("m3 here in gen_m4: ", m3_graph);
|
||||
// delta1 is transition in m1 that consists of only alphabet
|
||||
let delta1 = {};
|
||||
// m4_transitions = {state: {b: next, a: next}, ...}
|
||||
@@ -88,6 +88,7 @@ export function createM4(m1_graph) {
|
||||
}
|
||||
|
||||
if (paths.length > 0) {
|
||||
// Future: Deal with ambiguity matching! For now, we just defaults to first one
|
||||
// if (paths.length > 1) {
|
||||
// throw new Error("Ambiguous subgroup matching");
|
||||
// }
|
||||
@@ -118,6 +119,7 @@ export function createM4(m1_graph) {
|
||||
}
|
||||
}
|
||||
if (paths.length > 0) {
|
||||
// Future: Deal with ambiguity matching! For now, we just defaults to first one
|
||||
// if (paths.length > 1) {
|
||||
// throw new Error("Ambiguous subgroup matching in starting phase");
|
||||
// }
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// ============================================================================
|
||||
// NOT USED, left here in case of future use :)
|
||||
//==============================================================================
|
||||
// given simp_graph (plain dfa), return its reversed version.
|
||||
export function reverseDFA(simp_graph) {
|
||||
// simp_q = [
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import { regexToM1 } from "./gen";
|
||||
import { minDfa } from "./lexical";
|
||||
import {
|
||||
toNature,
|
||||
simplifyGraph,
|
||||
simplifyPlus,
|
||||
simplifyRegex,
|
||||
findSubstrings,
|
||||
} from "./gen_dfa";
|
||||
import { toNature, simplifyGraph, findSubstrings } from "./gen_dfa";
|
||||
import { M1ToM2 } from "./gen_m2";
|
||||
import { M2ToM3 } from "./gen_m3";
|
||||
import { createM4, registerToState } from "./gen_m4";
|
||||
@@ -231,8 +225,8 @@ export function regexSubmatchState(text, tagged_simp_graph) {
|
||||
let m4_graph = createM4(tagged_simp_graph);
|
||||
let tagged_m4_graph = registerToState(m4_graph);
|
||||
let final_m3_m4 = reassignM3M4(m3_graph, tagged_m4_graph);
|
||||
console.log("final m3: ", final_m3_m4["final_m3_graph"]);
|
||||
console.log("final m4: ", final_m3_m4["final_m4_graph"]);
|
||||
// console.log("final m3: ", final_m3_m4["final_m3_graph"]);
|
||||
// console.log("final m4: ", final_m3_m4["final_m4_graph"]);
|
||||
|
||||
// run reversed text via m3
|
||||
let m3_states = [];
|
||||
@@ -284,45 +278,9 @@ export function regexSubmatchState(text, tagged_simp_graph) {
|
||||
return submatch;
|
||||
}
|
||||
|
||||
// export function regexSubmatchState(text, tagged_simp_graph) {
|
||||
// let final_graph = findMatchStateTagged(tagged_simp_graph);
|
||||
// let allTags = final_graph["tags"];
|
||||
// let transitions = final_graph["transitions"];
|
||||
// console.log("final, gen_tagged_dfa: ", final_graph);
|
||||
// console.log("text, gen_tagged: ", text);
|
||||
// let submatch = {};
|
||||
// let latest_ele = {};
|
||||
// let latest_arr = {};
|
||||
// for (const tag in allTags) {
|
||||
// submatch[tag] = [];
|
||||
// latest_ele[tag] = -2;
|
||||
// latest_arr[tag] = -1;
|
||||
// }
|
||||
// // run through Transition
|
||||
// let node = final_graph["start_state"];
|
||||
|
||||
// for (let i = 0; i < text.length; i++) {
|
||||
// for (const tag in allTags) {
|
||||
// if (
|
||||
// allTags[tag].has(JSON.stringify([node, transitions[node][text[i]]]))
|
||||
// ) {
|
||||
// if (i == latest_ele[tag] + 1) {
|
||||
// submatch[tag][latest_arr[tag]].push(i);
|
||||
// } else {
|
||||
// submatch[tag].push([i]);
|
||||
// latest_arr[tag] += 1;
|
||||
// }
|
||||
// latest_ele[tag] = i;
|
||||
// }
|
||||
// }
|
||||
// node = transitions[node][text[i]];
|
||||
// }
|
||||
// return submatch;
|
||||
// }
|
||||
|
||||
export function finalRegexExtractState(regex, submatches, text) {
|
||||
const simp_graph = simplifyGraph(regex);
|
||||
console.log("min_dfa num states: ", simp_graph["states"].length);
|
||||
console.log("min_dfa num states: ", simp_graph["states"].size);
|
||||
const tagged_simp_graph = tagged_simplifyGraph(regex, submatches);
|
||||
console.log("tagged dfa num states: ", tagged_simp_graph["states"].length);
|
||||
const matched_dfa = findSubstrings(simp_graph, text);
|
||||
|
||||
44
src/test.js
44
src/test.js
@@ -1,17 +1,9 @@
|
||||
// file for testing outputs of these js files in src folder
|
||||
// Just console.log(what you want), and run "yarn testfunc"
|
||||
import { simplifyGraph, findSubstrings, simplifyRegex } from "./gen_dfa";
|
||||
import {
|
||||
tagged_simplifyGraph,
|
||||
findMatchStateTagged,
|
||||
formatForCircom,
|
||||
} from "./gen_tagged_dfa";
|
||||
import { reverseDFA } from "./gen_rev_dfa";
|
||||
import { gen_back_circom } from "./gen_back_circom";
|
||||
import { explore_gen_circom } from "./explore_gen_circom";
|
||||
import { explore_graph } from "./explore_graph";
|
||||
import { readSubmatch } from "./gen";
|
||||
import { gen_forw_circom } from "./gen_forw_circom";
|
||||
import { gen_all_circom } from "./gen_3steps_circom";
|
||||
import { gen_circom } from "./gen_circom";
|
||||
import { finalRegexExtractState } from "./gen_tagged_dfa";
|
||||
function test() {
|
||||
const text =
|
||||
"adsfasd DKI d=2211; DKI: v=12/; d=22; a=//121; d=1; bh=xUqTs2T2FPGCOB52 sdflj";
|
||||
@@ -40,30 +32,14 @@ function test() {
|
||||
[7, 59],
|
||||
[61, 70],
|
||||
];
|
||||
readSubmatch(regex, submatches);
|
||||
// const rev_graph = reverseDFA(simp_graph);
|
||||
// console.log("rev graph: ", rev_graph);
|
||||
// const matched_dfa = findSubstrings(simp_graph, text);
|
||||
// for (const subs of matched_dfa[1]) {
|
||||
// var matched = text.slice(subs[0], subs[1] + 1);
|
||||
// console.log("matched: ", matched);
|
||||
// }
|
||||
// const tagged_simp_graph = tagged_simplifyGraph(regex, submatches);
|
||||
// var final_graph = findMatchStateTagged(tagged_simp_graph);
|
||||
// var allTags = final_graph["tags"];
|
||||
// var transitions = final_graph["transitions"];
|
||||
// console.log("final graph: ", final_graph);
|
||||
// var circom_graph = formatForCircom(final_graph);
|
||||
// console.log("for rev graph");
|
||||
// var circom_rev_graph = formatForCircom(rev_graph);
|
||||
console.log("circom jyaa: ");
|
||||
// var result_circom = gen_back_circom(circom_rev_graph);
|
||||
// let circom = gen_forw_circom(regex, submatches);
|
||||
// let circom = gen_all_circom(regex, submatches);
|
||||
// readSubmatch(regex, submatches);
|
||||
finalRegexExtractState(regex, submatches, text);
|
||||
console.log("circom here: ");
|
||||
// test1: test generate circom circuit
|
||||
// let circom = gen_circom(regex, submatches);
|
||||
// console.log(circom);
|
||||
let result_circom = explore_gen_circom(regex, submatches);
|
||||
console.log("result circuit!!");
|
||||
// console.log(result_circom);
|
||||
// test 2: test those m1 - m4 stuffs, especially m3, m4
|
||||
// explore_graph(regex, submatches);
|
||||
console.log("Done!");
|
||||
}
|
||||
describe("test backend", function () {
|
||||
|
||||
Reference in New Issue
Block a user