Skip to content

Commit

Permalink
Feat/fix select regex reveal (#214)
Browse files Browse the repository at this point in the history
* Fix SelectRegexReveal

* Add a new test for the SelectRegexReveal template.
  • Loading branch information
SoraSuegami authored Aug 29, 2024
1 parent 4d34ccd commit d718290
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
117 changes: 117 additions & 0 deletions packages/circuits/tests/select-regex-reveal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { wasm } from "circom_tester";
import path from "path";


describe("Select Regex Reveal", () => {
jest.setTimeout(10 * 60 * 1000); // 10 minutes

let circuit: any;

beforeAll(async () => {
circuit = await wasm(
path.join(__dirname, "./test-circuits/select-regex-reveal-test.circom"),
{
recompile: true,
include: path.join(__dirname, "../../../node_modules"),
}
);
});

it("should reveal the substring with maximum revealed length", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = Math.floor(Math.random() * 24);
const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
const witness = await circuit.calculateWitness({
in: input,
startIndex: startIndex,
});
await circuit.checkConstraints(witness);
await circuit.assertOut(witness, { out: revealed })
});

it("should reveal the substring with non-maximum revealed length", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = 30;
const revealed = Array.from("zk").map(char => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
const witness = await circuit.calculateWitness({
in: input,
startIndex: startIndex,
});
await circuit.checkConstraints(witness);
await circuit.assertOut(witness, { out: revealed.concat([0, 0, 0, 0, 0, 0]) })
});

it("should fail when all zero", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = Math.floor(Math.random() * 32);
try {
const witness = await circuit.calculateWitness({
in: input,
startIndex: startIndex,
});
await circuit.checkConstraints(witness);
} catch (error) {
expect((error as Error).message).toMatch("Assert Failed");
}
});

it("should fail when startIndex is 0", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = 1 + Math.floor(Math.random() * 24);
const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
try {
const witness = await circuit.calculateWitness({
in: input,
startIndex: startIndex - 1,
});
await circuit.checkConstraints(witness);
} catch (error) {
expect((error as Error).message).toMatch("Assert Failed");
}
});

it("should fail when startIndex is not before 0", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = Math.floor(Math.random() * 23);
const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
try {
const witness = await circuit.calculateWitness({
in: input,
startIndex: startIndex + 1,
});
await circuit.checkConstraints(witness);
} catch (error) {
expect((error as Error).message).toMatch("Assert Failed");
}
});

it("should fail when startIndex is larger than max length", async function () {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const startIndex = Math.floor(Math.random() * 24);
const revealed = Array.from("zk email").map(char => char.charCodeAt(0));
for (let i = 0; i < revealed.length; i++) {
input[startIndex + i] = revealed[i];
}
try {
const witness = await circuit.calculateWitness({
in: input,
startIndex: 32
});
await circuit.checkConstraints(witness);
} catch (error) {
expect((error as Error).message).toMatch("Assert Failed");
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma circom 2.1.6;

include "../../utils/regex.circom";

component main = SelectRegexReveal(32,8);
5 changes: 5 additions & 0 deletions packages/circuits/utils/regex.circom
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ include "./bytes.circom";
/// @title SelectRegexReveal
/// @notice Returns reveal bytes of a regex match from the input
/// @notice Verifies data before and after (maxRevealLen) reveal part is zero
/// @notice Assumes that there is only one consecutive sequence of non-zero bytes in `in`.
/// @param maxArrayLen Maximum length of the input array
/// @param maxRevealLen Maximum length of the reveal part
/// @input in Input array; assumes elements to be bytes
Expand All @@ -26,6 +27,10 @@ template SelectRegexReveal(maxArrayLen, maxRevealLen) {
signal isPreviousZero[maxArrayLen];
signal isAboveMaxRevealLen[maxArrayLen];

// Assert startIndex < maxArrayLen
signal isValidStartIndex <== LessThan(bitLength)([startIndex, maxArrayLen]);
isValidStartIndex === 1;

isPreviousZero[0] <== 1;
for(var i = 0; i < maxArrayLen; i++) {
isStartIndex[i] <== IsEqual()([i, startIndex]);
Expand Down

0 comments on commit d718290

Please sign in to comment.