delete experiment files

This commit is contained in:
jernkun
2023-06-16 19:13:05 +07:00
parent f2fa5977db
commit b246100269
10 changed files with 41 additions and 2543 deletions

View File

@@ -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
View 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"]);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 };

View File

@@ -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");
// }

View File

@@ -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 = [

View File

@@ -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);

View File

@@ -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 () {