Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): add extractor witness gen #90

Merged
merged 12 commits into from
Sep 13, 2024
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ edition = "2021"
serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127"
clap = { version = "4.5.16", features = ["derive"] }
regex = "1.10.6"
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
</h1>

<div align="center">
<a href="https://github.com/pluto/extractor/graphs/contributors">
<a href="https://github.com/pluto/parser-attestor/graphs/contributors">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THANKS!

<img src="https://img.shields.io/github/contributors/pluto/spark?style=flat-square&logo=github&logoColor=8b949e&labelColor=282f3b&color=32c955" alt="Contributors" />
</a>
<a href="https://github.com/pluto/extractor/actions/workflows/test.yaml">
<a href="https://github.com/pluto/parser-attestor/actions/workflows/test.yaml">
<img src="https://img.shields.io/badge/tests-passing-32c955?style=flat-square&logo=github-actions&logoColor=8b949e&labelColor=282f3b" alt="Tests" />
</a>
<a href="https://github.com/pluto/extractor/actions/workflows/lint.yaml">
<a href="https://github.com/pluto/parser-attestor/actions/workflows/lint.yaml">
<img src="https://img.shields.io/badge/lint-passing-32c955?style=flat-square&logo=github-actions&logoColor=8b949e&labelColor=282f3b" alt="Lint" />
</a>
</div>
Expand Down Expand Up @@ -120,10 +120,10 @@ From the root of this repository, run:
```sh
cargo install --path .
```
to install the `wpbuild` binary.
to install the `pabuild` binary.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOUBLE THANKS

You can see a help menu with the subcommands by:
```sh
wpbuild --help
pabuild --help
```
This is our local Rust command line application.
Please see the [documentation](docs/pabuild.md) for how to use this alongside the other tools.
Expand Down
2 changes: 1 addition & 1 deletion circuits/http/extractor.circom
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ template ExtractResponse(DATA_BYTES, maxContentLength) {
valueStartingIndex[i] <== valueStartingIndex[i-1] + i * (1-isZeroMask[i]) * isPrevStartingIndex[i];
}

response <== SelectSubArray(DATA_BYTES, maxContentLength)(dataMask, valueStartingIndex[DATA_BYTES-1]+1, DATA_BYTES - valueStartingIndex[DATA_BYTES-1]);
response <== SelectSubArray(DATA_BYTES, maxContentLength)(dataMask, valueStartingIndex[DATA_BYTES-1]+1, maxContentLength);
}

template ExtractHeaderValue(DATA_BYTES, headerNameLength, maxValueLength) {
Expand Down
27 changes: 16 additions & 11 deletions circuits/test/http/codegen.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ interface Response {
}


function executeCodegen(inputFilename: string, outputFilename: string) {
function executeCodegen(circuitName: string, inputFileName: string, lockfileName: string) {
return new Promise((resolve, reject) => {
const inputPath = join(__dirname, "..", "..", "..", "examples", "http", "lockfile", inputFilename);
const inputFilePath = join(__dirname, "..", "..", "..", "examples", "http", inputFileName);
const lockfilePath = join(__dirname, "..", "..", "..", "examples", "http", "lockfile", lockfileName);

const codegen = spawn("cargo", ["run", "http", "--lockfile", inputPath, "--output-filename", outputFilename]);
const codegen = spawn("cargo", ["run", "codegen", "http", "--circuit-name", circuitName, "--input-file", inputFilePath, "--lockfile", lockfilePath]);
Autoparallel marked this conversation as resolved.
Show resolved Hide resolved

codegen.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
Expand All @@ -71,9 +72,10 @@ describe("HTTP :: Codegen :: Request", async () => {
it("(valid) GET:", async () => {
let lockfile = "request.lock";
let inputfile = "get_request.http";
let circuitName = "get_request_test";

// generate extractor circuit using codegen
await executeCodegen(`${lockfile}.json`, lockfile);
await executeCodegen(circuitName, inputfile, `${lockfile}.json`);

const lockData = readLockFile<Request>(`${lockfile}.json`);
console.log("lockData: ", JSON.stringify(lockData));
Expand All @@ -89,7 +91,7 @@ describe("HTTP :: Codegen :: Request", async () => {


circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${lockfile}`,
file: `main/http_${circuitName}`,
template: "LockHTTPRequest",
params: params,
});
Expand All @@ -113,9 +115,10 @@ describe("HTTP :: Codegen :: Request", async () => {
it("(invalid) GET:", async () => {
let lockfile = "request.lock";
let inputfile = "get_request.http";
let circuitName = "get_request_test";

// generate extractor circuit using codegen
await executeCodegen(`${lockfile}.json`, lockfile);
await executeCodegen(circuitName, inputfile, `${lockfile}.json`);

const lockData = readLockFile<Request>(`${lockfile}.json`);

Expand All @@ -130,7 +133,7 @@ describe("HTTP :: Codegen :: Request", async () => {


circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${lockfile}`,
file: `main/http_${circuitName}`,
template: "LockHTTPRequest",
params: params,
});
Expand Down Expand Up @@ -159,9 +162,10 @@ describe("HTTP :: Codegen :: Response", async () => {
it("(valid) GET:", async () => {
let lockfile = "response.lock";
let inputfile = "get_response.http";
let circuitName = "get_response_test";

// generate extractor circuit using codegen
await executeCodegen(`${lockfile}.json`, lockfile);
await executeCodegen(circuitName, inputfile, `${lockfile}.json`);

const lockData = readLockFile<Response>(`${lockfile}.json`);
console.log("lockData: ", JSON.stringify(lockData));
Expand All @@ -179,7 +183,7 @@ describe("HTTP :: Codegen :: Response", async () => {


circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${lockfile}`,
file: `main/http_${circuitName}`,
template: "LockHTTPResponse",
params: params,
});
Expand All @@ -205,9 +209,10 @@ describe("HTTP :: Codegen :: Response", async () => {
it("(invalid) GET:", async () => {
let lockfile = "response.lock";
let inputfile = "get_response.http";
let circuitName = "get_response_test";

// generate extractor circuit using codegen
await executeCodegen(`${lockfile}.json`, lockfile);
await executeCodegen(circuitName, inputfile, `${lockfile}.json`);

const lockData = readLockFile<Response>(`${lockfile}.json`);

Expand All @@ -224,7 +229,7 @@ describe("HTTP :: Codegen :: Response", async () => {


circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${lockfile}`,
file: `main/http_${circuitName}`,
template: "LockHTTPResponse",
params: params,
});
Expand Down
11 changes: 1 addition & 10 deletions circuits/test/http/extractor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe("HTTP :: body Extractor", async () => {

let output3 = parsedHttp.bodyBytes.slice(0);
output3.pop();
// output3.pop(); // TODO: fails due to shift subarray bug
output3.pop();
generatePassCase(parsedHttp.input, output3, "output length less than actual length");
});

Expand Down Expand Up @@ -75,15 +75,6 @@ describe("HTTP :: header Extractor", async () => {
let parsedHttp = readHTTPInputFile("get_response.http");

generatePassCase(parsedHttp.input, toByte("Content-Length"), toByte(parsedHttp.headers["Content-Length"]), "");

// let output2 = parsedHttp.bodyBytes.slice(0);
// output2.push(0, 0, 0, 0);
// generatePassCase(parsedHttp.input, output2, "output length more than actual length");

// let output3 = parsedHttp.bodyBytes.slice(0);
// output3.pop();
// // output3.pop(); // TODO: fails due to shift subarray bug
// generatePassCase(parsedHttp.input, output3, "output length less than actual length");
});
});

46 changes: 25 additions & 21 deletions circuits/test/json/extractor/extractor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { join } from "path";
import { spawn } from "child_process";


function executeCodegen(inputFilename: string, outputFilename: string) {
function executeCodegen(circuitName: string, inputFileName: string, lockfileName: string) {
return new Promise((resolve, reject) => {
const inputPath = join(__dirname, "..", "..", "..", "..", "examples", "json", "lockfile", inputFilename);
const inputFilePath = join(__dirname, "..", "..", "..", "..", "examples", "json", "test", inputFileName);
const lockfilePath = join(__dirname, "..", "..", "..", "..", "examples", "json", "lockfile", lockfileName);

const codegen = spawn("cargo", ["run", "json", "--template", inputPath, "--output-filename", outputFilename]);
const codegen = spawn("cargo", ["run", "codegen", "json", "--circuit-name", circuitName, "--input-file", inputFilePath, "--lockfile", lockfilePath]);

codegen.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
Expand All @@ -34,13 +35,13 @@ describe("ExtractValue", async () => {
let filename = "value_string";

// generate extractor circuit using codegen
await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);

// read JSON input file into bytes
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["k"]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractStringValue",
params: [input.length, 1, 1, 0, 1],
});
Expand All @@ -56,11 +57,11 @@ describe("ExtractValue", async () => {

it("two_keys: {\"key1\": \"abc\", \"key2\": \"def\" }", async () => {
let filename = "two_keys"
await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["key2"]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractStringValue",
params: [input.length, 1, 4, 0, 3],
});
Expand All @@ -71,11 +72,11 @@ describe("ExtractValue", async () => {

it("value_number: {\"k\": 69 }", async () => {
let filename = "value_number";
await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["k"]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractNumValue",
params: [input.length, 1, 1, 0, 2],
});
Expand All @@ -88,13 +89,14 @@ describe("ExtractValue", async () => {

it("value_array_string: { \"k\" : [ 420 , 69 , 4200 , 600 ], \"b\": [ \"ab\" , \"ba\", \"ccc\", \"d\" ] }", async () => {
let filename = "value_array_string";
await executeCodegen(`${filename}.json`, filename);
let inputFileName = "value_array.json";
await executeCodegen(`${filename}_test`, inputFileName, `${filename}.json`);

for (let i = 0; i < 4; i++) {
let [input, keyUnicode, output] = readJSONInputFile("value_array.json", ["b", i]);
let [input, keyUnicode, output] = readJSONInputFile(inputFileName, ["b", i]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractStringValue",
params: [input.length, 2, 1, 0, i, 1, output.length],
});
Expand All @@ -106,13 +108,15 @@ describe("ExtractValue", async () => {

it("value_array_number: { \"k\" : [ 420 , 69 , 4200 , 600 ], \"b\": [ \"ab\" , \"ba\", \"ccc\", \"d\" ] }", async () => {
let filename = "value_array_number";
await executeCodegen(`${filename}.json`, filename);
let inputFileName = "value_array.json";

await executeCodegen(`${filename}_test`, inputFileName, `${filename}.json`);

for (let i = 0; i < 4; i++) {
let [input, keyUnicode, output] = readJSONInputFile("value_array.json", ["k", i]);
let [input, keyUnicode, output] = readJSONInputFile(inputFileName, ["k", i]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractNumValue",
params: [input.length, 2, 1, 0, i, 1, output.length],
});
Expand All @@ -125,13 +129,13 @@ describe("ExtractValue", async () => {

it("value_array_nested: { \"a\": [[1,0],[0,1,3]] }", async () => {
let filename = "value_array_nested";
await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);
let index_0 = 1;
let index_1 = 0;
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a", index_0, index_1]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractNumValue",
params: [input.length, 3, 1, 0, index_0, 1, index_1, 2, 1],
});
Expand All @@ -150,12 +154,12 @@ describe("ExtractValueMultiDepth", () => {
it("value_object: { \"a\": { \"d\" : \"e\", \"e\": \"c\" }, \"e\": { \"f\": \"a\", \"e\": \"2\" } }", async () => {
let filename = "value_object";

await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);

let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["e", "e"]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractStringValue",
params: [input.length, 3, 1, 0, 1, 1, 1],
});
Expand All @@ -176,14 +180,14 @@ describe("ExtractValueArrayObject", () => {
it("value_array_object: {\"a\":[{\"b\":[1,4]},{\"c\":\"b\"}]}", async () => {
let filename = "value_array_object";

await executeCodegen(`${filename}.json`, filename);
await executeCodegen(`${filename}_test`, `${filename}.json`, `${filename}.json`);

let index_0 = 0;
let index_1 = 0;
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a", index_0, "b", index_1]);

circuit = await circomkit.WitnessTester(`Extract`, {
file: `main/${filename}`,
file: `main/json_${filename}_test`,
template: "ExtractNumValue",
params: [input.length, 4, 1, 0, index_0, 1, 1, 2, index_1, 3, 1],
});
Expand Down
Loading