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

refactor: organize circuits and begin HTTP parsing #65

Merged
merged 7 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ npx circomkit clean extract

All of the above should be ran from repository root.

## Rust Example Witness JSON Creation
To generate example input JSON files for the Circom circuits, you can
```
cargo install --path .
```
to install the `witness` binary.
To get the basic idea, run `witness --help`.
It can process and generate JSON files to be used for the circuits.
For example, if we have a given JSON file we want to parse such as `examples/json/test/example.json` for the `extract` circuit (see `circuits.json`), then we can:
```
witness json --input-file examples/json/test/example.json --output-dir inputs/extract --output-filename input.json
```

For an HTTP request/response, you can generate a JSON input via:
```
witness http --input-file examples/http/get_request.http --output-dir inputs/get_request --output-filename input.json
```
Afterwards, you can run `circomkit compile get_request` then `circomkit witness get_request input`.

## Testing
To test, you can just run
```
Expand Down
37 changes: 21 additions & 16 deletions circuits.json
Original file line number Diff line number Diff line change
@@ -1,63 +1,63 @@
{
"extract": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
157,
13
]
},
"value_string": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
12,
1
]
},
"value_number": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
12,
2
]
},
"value_array": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
18,
2
]
},
"value_array_nested": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
24,
4
]
},
"value_array_object": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
25,
4
]
},
"value_array_object_array": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
31,
5
]
},
"value_object": {
"file": "extract",
"template": "Extract",
"file": "parser_json/parser",
"template": "Parser",
"params": [
21,
3
Expand All @@ -70,5 +70,10 @@
787,
10
]
},
"get_request": {
"file": "parser_http_request/parser",
"template": "Parser",
"params": [158]
}
}
49 changes: 49 additions & 0 deletions circuits/parser_http_request/language.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
pragma circom 2.1.9;

// All the possible request methods: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods

template Syntax() {
//-Delimeters---------------------------------------------------------------------------------//
// - ASCII char `:`
signal output COLON <== 58;
// - ASCII char `;`
signal output SEMICOLON <== 59;
// - ASCII char `,`
signal output COMMA <== 44;
// - ASCII char `"`
signal output QUOTE <== 34;
//-White_space--------------------------------------------------------------------------------//
// - ASCII pair: `\r\n`
signal output CLRF <== [13, 10]; // https://www.rfc-editor.org/rfc/rfc2616#section-2.2
// https://www.rfc-editor.org/rfc/rfc7230#section-3.5
// - ASCII char: ` `
signal output SPACE <== 32;
//-Escape-------------------------------------------------------------------------------------//
// - ASCII char: `\`
signal output ESCAPE <== 92;
}

template RequestMethod() {
signal output GET[3] <== [71, 69, 84];
// signal output HEAD[4] <== [72, 69, 65, 68];
signal output POST[4] <== [80, 79, 83, 84];
// signal output PUT <== 3;
// signal output DELETE <== 4;
// signal output CONNECT <== 5;
// signal output OPTIONS <== 6;
// signal output TRACE <== 7;
// signal output PATCH <== 8;
}

// NOTE: Starting at 1 to avoid a false positive with a 0.
template RequestMethodTag() {
signal output GET <== 1;
// signal output HEAD <== 2;
signal output POST <== 3;
// signal output PUT <== 4;
// signal output DELETE <== 5;
// signal output CONNECT <== 6;
// signal output OPTIONS <== 7;
// signal output TRACE <== 8;
// signal output PATCH <== 9;
}
28 changes: 28 additions & 0 deletions circuits/parser_http_request/machine.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
pragma circom 2.1.9;

include "language.circom";
include "../utils/array.circom";

template ParseMethod() {
signal input bytes[7];
signal output MethodTag;

component RequestMethod = RequestMethod();
component RequestMethodTag = RequestMethodTag();

component IsGet = IsEqualArray(3);
for(var byte_idx = 0; byte_idx < 3; byte_idx++) {
IsGet.in[0][byte_idx] <== bytes[byte_idx];
IsGet.in[1][byte_idx] <== RequestMethod.GET[byte_idx];
}
signal TagGet <== IsGet.out * RequestMethodTag.GET;

component IsPost = IsEqualArray(4);
for(var byte_idx = 0; byte_idx < 4; byte_idx++) {
IsPost.in[0][byte_idx] <== bytes[byte_idx];
IsPost.in[1][byte_idx] <== RequestMethod.POST[byte_idx];
}
signal TagPost <== IsPost.out * RequestMethodTag.POST;

MethodTag <== TagGet + TagPost;
}
24 changes: 24 additions & 0 deletions circuits/parser_http_request/parser.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
pragma circom 2.1.9;

include "../utils/bytes.circom";
include "machine.circom";


template Parser(DATA_BYTES) {
signal input data[DATA_BYTES];

signal output Method;

//--------------------------------------------------------------------------------------------//
//-CONSTRAINTS--------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------------//
component dataASCII = ASCII(DATA_BYTES);
dataASCII.in <== data;
//--------------------------------------------------------------------------------------------//

component ParseMethod = ParseMethod();
for(var byte_idx = 0; byte_idx < 7; byte_idx++) {
ParseMethod.bytes[byte_idx] <== data[byte_idx];
}
log("MethodTag: ", ParseMethod.MethodTag);
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
# `parser`
# `machine`
This module consists of the core parsing components for generating proofs of selective disclosure in JSON.

## Layout
Expand All @@ -23,9 +23,9 @@ Tests for this module are located in the files: `circuits/test/parser/*.test.ts

pragma circom 2.1.9;

include "./utils/array.circom";
include "./utils/bytes.circom";
include "./utils/operators.circom";
include "../utils/array.circom";
include "../utils/bytes.circom";
include "../utils/operators.circom";
include "language.circom";

/*
Expand Down
34 changes: 17 additions & 17 deletions circuits/extract.circom → circuits/parser_json/parser.circom
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
pragma circom 2.1.9;

include "./utils/bytes.circom";
include "parser.circom";
include "../utils/bytes.circom";
include "machine.circom";

template Extract(DATA_BYTES, MAX_STACK_HEIGHT) {
template Parser(DATA_BYTES, MAX_STACK_HEIGHT) {
signal input data[DATA_BYTES];

// TODO: Add assertions on the inputs here!
Expand Down Expand Up @@ -31,23 +31,23 @@ template Extract(DATA_BYTES, MAX_STACK_HEIGHT) {
State[data_idx].parsing_string <== State[data_idx - 1].next_parsing_string;
State[data_idx].parsing_number <== State[data_idx - 1].next_parsing_number;

// Debugging
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", data_idx, "].stack[", i,"] ", "= [",State[data_idx].stack[i][0], "][", State[data_idx].stack[i][1],"]" );
}
log("State[", data_idx, "].parsing_string", "= ", State[data_idx].parsing_string);
log("State[", data_idx, "].parsing_number", "= ", State[data_idx].parsing_number);
log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
// // Debugging
// for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
// log("State[", data_idx, "].stack[", i,"] ", "= [",State[data_idx].stack[i][0], "][", State[data_idx].stack[i][1],"]" );
// }
// log("State[", data_idx, "].parsing_string", "= ", State[data_idx].parsing_string);
// log("State[", data_idx, "].parsing_number", "= ", State[data_idx].parsing_number);
// log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}

// Constrain to have valid JSON (TODO: more is needed)
// State[DATA_BYTES - 1].next_tree_depth === 0;

// Debugging
for(var i = 0; i < MAX_STACK_HEIGHT; i++) {
log("State[", DATA_BYTES, "].stack[", i,"] ", "= [",State[DATA_BYTES -1].next_stack[i][0], "][", State[DATA_BYTES - 1].next_stack[i][1],"]" );
}
log("State[", DATA_BYTES, "].parsing_string", "= ", State[DATA_BYTES-1].next_parsing_string);
log("State[", DATA_BYTES, "].parsing_number", "= ", State[DATA_BYTES-1].next_parsing_number);
log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
// // Debugging
// for(var i = 0; i < MAX_STACK_HEIGHT; i++) {
// log("State[", DATA_BYTES, "].stack[", i,"] ", "= [",State[DATA_BYTES -1].next_stack[i][0], "][", State[DATA_BYTES - 1].next_stack[i][1],"]" );
// }
// log("State[", DATA_BYTES, "].parsing_string", "= ", State[DATA_BYTES-1].next_parsing_string);
// log("State[", DATA_BYTES, "].parsing_number", "= ", State[DATA_BYTES-1].next_parsing_number);
// log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,9 @@ describe("StateUpdate", () => {
});
}

function generateFailCase(input: any, desc: string) {
const description = generateDescription(input);

it(`(valid) witness: ${description}\n${desc}`, async () => {
await circuit.expectFail(input);
});
}

before(async () => {
circuit = await circomkit.WitnessTester(`StateUpdate`, {
file: "circuits/parser",
file: "circuits/parser_json/machine",
template: "StateUpdate",
params: [4],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe("GetTopOfStack", () => {
let circuit: WitnessTester<["stack"], ["value", "pointer"]>;
before(async () => {
circuit = await circomkit.WitnessTester(`GetTopOfStack`, {
file: "circuits/parser",
file: "circuits/parser_json/machine",
template: "GetTopOfStack",
params: [4],
});
Expand Down Expand Up @@ -44,7 +44,7 @@ describe("StateUpdate :: RewriteStack", () => {
>;
before(async () => {
circuit = await circomkit.WitnessTester(`GetTopOfStack`, {
file: "circuits/parser",
file: "circuits/parser_json/machine",
template: "StateUpdate",
params: [4],
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("StateUpdate :: Values", () => {
>;
before(async () => {
circuit = await circomkit.WitnessTester(`GetTopOfStack`, {
file: "circuits/parser",
file: "circuits/parser_json/machine",
template: "StateUpdate",
params: [4],
});
Expand Down
5 changes: 5 additions & 0 deletions examples/http/get_request.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GET /objectserver/restapi/alerts/status HTTP/1.1
Accept: application/json
Authorization: Basic dGVzdHVzZXIwMTpuZXRjb29s
Host: localhost
Connection: keep-alive
5 changes: 5 additions & 0 deletions examples/http/get_response.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 19

{"success":"true"}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
14 changes: 0 additions & 14 deletions json_examples/reddit_response.json

This file was deleted.

7 changes: 0 additions & 7 deletions json_examples/sambhav_example.json

This file was deleted.

Loading
Loading