From b1fd284589a67084db25bf7673ab48e80c2b98d3 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 27 Aug 2024 14:12:47 -0600 Subject: [PATCH 1/7] refactor: circuits --- circuits/{ => json_parser}/language.circom | 0 .../machine.circom} | 8 ++--- .../parser.circom} | 34 +++++++++---------- .../test/{parser => json_parser}/index.ts | 0 .../parsing_types.test.ts} | 10 +----- .../{parser => json_parser}/stack.test.ts | 4 +-- .../{parser => json_parser}/values.test.ts | 2 +- package-lock.json | 3 ++ 8 files changed, 28 insertions(+), 33 deletions(-) rename circuits/{ => json_parser}/language.circom (100%) rename circuits/{parser.circom => json_parser/machine.circom} (99%) rename circuits/{extract.circom => json_parser/parser.circom} (56%) rename circuits/test/{parser => json_parser}/index.ts (100%) rename circuits/test/{parser/parser.test.ts => json_parser/parsing_types.test.ts} (93%) rename circuits/test/{parser => json_parser}/stack.test.ts (99%) rename circuits/test/{parser => json_parser}/values.test.ts (99%) diff --git a/circuits/language.circom b/circuits/json_parser/language.circom similarity index 100% rename from circuits/language.circom rename to circuits/json_parser/language.circom diff --git a/circuits/parser.circom b/circuits/json_parser/machine.circom similarity index 99% rename from circuits/parser.circom rename to circuits/json_parser/machine.circom index 0f63120..9fda500 100644 --- a/circuits/parser.circom +++ b/circuits/json_parser/machine.circom @@ -1,5 +1,5 @@ /* -# `parser` +# `machine` This module consists of the core parsing components for generating proofs of selective disclosure in JSON. ## Layout @@ -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"; /* diff --git a/circuits/extract.circom b/circuits/json_parser/parser.circom similarity index 56% rename from circuits/extract.circom rename to circuits/json_parser/parser.circom index 8fa4bdb..f3e4b51 100644 --- a/circuits/extract.circom +++ b/circuits/json_parser/parser.circom @@ -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! @@ -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 { }); } - 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/json_parser/machine", template: "StateUpdate", params: [4], }); diff --git a/circuits/test/parser/stack.test.ts b/circuits/test/json_parser/stack.test.ts similarity index 99% rename from circuits/test/parser/stack.test.ts rename to circuits/test/json_parser/stack.test.ts index 69e0b1a..f4bf81a 100644 --- a/circuits/test/parser/stack.test.ts +++ b/circuits/test/json_parser/stack.test.ts @@ -5,7 +5,7 @@ describe("GetTopOfStack", () => { let circuit: WitnessTester<["stack"], ["value", "pointer"]>; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/parser", + file: "circuits/json_parser/machine", template: "GetTopOfStack", params: [4], }); @@ -44,7 +44,7 @@ describe("StateUpdate :: RewriteStack", () => { >; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/parser", + file: "circuits/json_parser/machine", template: "StateUpdate", params: [4], }); diff --git a/circuits/test/parser/values.test.ts b/circuits/test/json_parser/values.test.ts similarity index 99% rename from circuits/test/parser/values.test.ts rename to circuits/test/json_parser/values.test.ts index 7b6bd9f..2c93cfe 100644 --- a/circuits/test/parser/values.test.ts +++ b/circuits/test/json_parser/values.test.ts @@ -8,7 +8,7 @@ describe("StateUpdate :: Values", () => { >; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/parser", + file: "circuits/json_parser/machine", template: "StateUpdate", params: [4], }); diff --git a/package-lock.json b/package-lock.json index 28ce12c..f7ac343 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,12 @@ { "name": "extractor", + "version": "0.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "extractor", + "version": "0.1.0", "license": "Apache-2.0", "dependencies": { "circomkit": "^0.2.1", From 23a68bbd806cdf2bd4700099f5a1516726be842a Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 27 Aug 2024 14:43:14 -0600 Subject: [PATCH 2/7] add HTTP to Rust witness creation --- README.md | 18 ++++ circuits.json | 32 +++---- .../language.circom | 0 .../machine.circom | 0 .../parser.circom | 0 .../{json_parser => parser_json}/index.ts | 0 .../parsing_types.test.ts | 2 +- .../stack.test.ts | 4 +- .../values.test.ts | 2 +- examples/http/get_request.http | 5 ++ examples/http/get_response.http | 7 ++ .../json}/response/reddit.json | 0 .../json}/response/spotify.json | 0 .../json}/response/venmo.json | 0 .../json}/test/example.json | 0 .../json}/test/string_escape.json | 0 .../json}/test/two_keys.json | 0 .../json}/test/value_array.json | 0 .../json}/test/value_array_nested.json | 0 .../json}/test/value_array_object.json | 0 .../json}/test/value_array_object_array.json | 0 .../json}/test/value_number.json | 0 .../json}/test/value_object.json | 0 .../json}/test/value_string.json | 0 json_examples/reddit_response.json | 14 --- json_examples/sambhav_example.json | 7 -- json_examples/test/example_json.md | 25 ------ json_examples/test_depth.json | 6 -- json_examples/test_two_key.json | 4 - src/main.rs | 90 ++++++++++++------- 30 files changed, 108 insertions(+), 108 deletions(-) rename circuits/{json_parser => parser_json}/language.circom (100%) rename circuits/{json_parser => parser_json}/machine.circom (100%) rename circuits/{json_parser => parser_json}/parser.circom (100%) rename circuits/test/{json_parser => parser_json}/index.ts (100%) rename circuits/test/{json_parser => parser_json}/parsing_types.test.ts (98%) rename circuits/test/{json_parser => parser_json}/stack.test.ts (99%) rename circuits/test/{json_parser => parser_json}/values.test.ts (99%) create mode 100644 examples/http/get_request.http create mode 100644 examples/http/get_response.http rename {json_examples => examples/json}/response/reddit.json (100%) rename {json_examples => examples/json}/response/spotify.json (100%) rename {json_examples => examples/json}/response/venmo.json (100%) rename {json_examples => examples/json}/test/example.json (100%) rename {json_examples => examples/json}/test/string_escape.json (100%) rename {json_examples => examples/json}/test/two_keys.json (100%) rename {json_examples => examples/json}/test/value_array.json (100%) rename {json_examples => examples/json}/test/value_array_nested.json (100%) rename {json_examples => examples/json}/test/value_array_object.json (100%) rename {json_examples => examples/json}/test/value_array_object_array.json (100%) rename {json_examples => examples/json}/test/value_number.json (100%) rename {json_examples => examples/json}/test/value_object.json (100%) rename {json_examples => examples/json}/test/value_string.json (100%) delete mode 100644 json_examples/reddit_response.json delete mode 100644 json_examples/sambhav_example.json delete mode 100644 json_examples/test/example_json.md delete mode 100644 json_examples/test_depth.json delete mode 100644 json_examples/test_two_key.json diff --git a/README.md b/README.md index 35382e0..8a5ceb1 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,24 @@ 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 +``` + ## Testing To test, you can just run ``` diff --git a/circuits.json b/circuits.json index 59c7f4f..5799800 100644 --- a/circuits.json +++ b/circuits.json @@ -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 diff --git a/circuits/json_parser/language.circom b/circuits/parser_json/language.circom similarity index 100% rename from circuits/json_parser/language.circom rename to circuits/parser_json/language.circom diff --git a/circuits/json_parser/machine.circom b/circuits/parser_json/machine.circom similarity index 100% rename from circuits/json_parser/machine.circom rename to circuits/parser_json/machine.circom diff --git a/circuits/json_parser/parser.circom b/circuits/parser_json/parser.circom similarity index 100% rename from circuits/json_parser/parser.circom rename to circuits/parser_json/parser.circom diff --git a/circuits/test/json_parser/index.ts b/circuits/test/parser_json/index.ts similarity index 100% rename from circuits/test/json_parser/index.ts rename to circuits/test/parser_json/index.ts diff --git a/circuits/test/json_parser/parsing_types.test.ts b/circuits/test/parser_json/parsing_types.test.ts similarity index 98% rename from circuits/test/json_parser/parsing_types.test.ts rename to circuits/test/parser_json/parsing_types.test.ts index 610d8c1..fce76bf 100644 --- a/circuits/test/json_parser/parsing_types.test.ts +++ b/circuits/test/parser_json/parsing_types.test.ts @@ -19,7 +19,7 @@ describe("StateUpdate", () => { before(async () => { circuit = await circomkit.WitnessTester(`StateUpdate`, { - file: "circuits/json_parser/machine", + file: "circuits/parser_json/machine", template: "StateUpdate", params: [4], }); diff --git a/circuits/test/json_parser/stack.test.ts b/circuits/test/parser_json/stack.test.ts similarity index 99% rename from circuits/test/json_parser/stack.test.ts rename to circuits/test/parser_json/stack.test.ts index f4bf81a..ff5e97a 100644 --- a/circuits/test/json_parser/stack.test.ts +++ b/circuits/test/parser_json/stack.test.ts @@ -5,7 +5,7 @@ describe("GetTopOfStack", () => { let circuit: WitnessTester<["stack"], ["value", "pointer"]>; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/json_parser/machine", + file: "circuits/parser_json/machine", template: "GetTopOfStack", params: [4], }); @@ -44,7 +44,7 @@ describe("StateUpdate :: RewriteStack", () => { >; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/json_parser/machine", + file: "circuits/parser_json/machine", template: "StateUpdate", params: [4], }); diff --git a/circuits/test/json_parser/values.test.ts b/circuits/test/parser_json/values.test.ts similarity index 99% rename from circuits/test/json_parser/values.test.ts rename to circuits/test/parser_json/values.test.ts index 2c93cfe..d96e757 100644 --- a/circuits/test/json_parser/values.test.ts +++ b/circuits/test/parser_json/values.test.ts @@ -8,7 +8,7 @@ describe("StateUpdate :: Values", () => { >; before(async () => { circuit = await circomkit.WitnessTester(`GetTopOfStack`, { - file: "circuits/json_parser/machine", + file: "circuits/parser_json/machine", template: "StateUpdate", params: [4], }); diff --git a/examples/http/get_request.http b/examples/http/get_request.http new file mode 100644 index 0000000..88eb48d --- /dev/null +++ b/examples/http/get_request.http @@ -0,0 +1,5 @@ +GET /objectserver/restapi/alerts/status HTTP/1.1 +Accept: application/json +Authorization: Basic dGVzdHVzZXIwMTpuZXRjb29s +Host: localhost +Connection: keep-alive \ No newline at end of file diff --git a/examples/http/get_response.http b/examples/http/get_response.http new file mode 100644 index 0000000..423643b --- /dev/null +++ b/examples/http/get_response.http @@ -0,0 +1,7 @@ +HTTP/1.1 200 OK +Cache-Control: no-cache +Server: libnhttpd +Date: Wed Jul 4 15:32:03 2012 +Connection: Keep-Alive: +Content-Type: application/rdf+xml +Content-Length: 24860 \ No newline at end of file diff --git a/json_examples/response/reddit.json b/examples/json/response/reddit.json similarity index 100% rename from json_examples/response/reddit.json rename to examples/json/response/reddit.json diff --git a/json_examples/response/spotify.json b/examples/json/response/spotify.json similarity index 100% rename from json_examples/response/spotify.json rename to examples/json/response/spotify.json diff --git a/json_examples/response/venmo.json b/examples/json/response/venmo.json similarity index 100% rename from json_examples/response/venmo.json rename to examples/json/response/venmo.json diff --git a/json_examples/test/example.json b/examples/json/test/example.json similarity index 100% rename from json_examples/test/example.json rename to examples/json/test/example.json diff --git a/json_examples/test/string_escape.json b/examples/json/test/string_escape.json similarity index 100% rename from json_examples/test/string_escape.json rename to examples/json/test/string_escape.json diff --git a/json_examples/test/two_keys.json b/examples/json/test/two_keys.json similarity index 100% rename from json_examples/test/two_keys.json rename to examples/json/test/two_keys.json diff --git a/json_examples/test/value_array.json b/examples/json/test/value_array.json similarity index 100% rename from json_examples/test/value_array.json rename to examples/json/test/value_array.json diff --git a/json_examples/test/value_array_nested.json b/examples/json/test/value_array_nested.json similarity index 100% rename from json_examples/test/value_array_nested.json rename to examples/json/test/value_array_nested.json diff --git a/json_examples/test/value_array_object.json b/examples/json/test/value_array_object.json similarity index 100% rename from json_examples/test/value_array_object.json rename to examples/json/test/value_array_object.json diff --git a/json_examples/test/value_array_object_array.json b/examples/json/test/value_array_object_array.json similarity index 100% rename from json_examples/test/value_array_object_array.json rename to examples/json/test/value_array_object_array.json diff --git a/json_examples/test/value_number.json b/examples/json/test/value_number.json similarity index 100% rename from json_examples/test/value_number.json rename to examples/json/test/value_number.json diff --git a/json_examples/test/value_object.json b/examples/json/test/value_object.json similarity index 100% rename from json_examples/test/value_object.json rename to examples/json/test/value_object.json diff --git a/json_examples/test/value_string.json b/examples/json/test/value_string.json similarity index 100% rename from json_examples/test/value_string.json rename to examples/json/test/value_string.json diff --git a/json_examples/reddit_response.json b/json_examples/reddit_response.json deleted file mode 100644 index 163e6b4..0000000 --- a/json_examples/reddit_response.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "data": { - "redditorInfoByName": { - "id": "t2_bepsb", - "karma": { - "fromAwardsGiven": 0, - "fromAwardsReceived": 470, - "fromComments": 9583, - "fromPosts": 13228, - "total": 23281 - } - } - } -} \ No newline at end of file diff --git a/json_examples/sambhav_example.json b/json_examples/sambhav_example.json deleted file mode 100644 index ab9c57e..0000000 --- a/json_examples/sambhav_example.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extract": { - "file": "extract", - "template": "Extract", - "params": "" - } -} \ No newline at end of file diff --git a/json_examples/test/example_json.md b/json_examples/test/example_json.md deleted file mode 100644 index a398ff8..0000000 --- a/json_examples/test/example_json.md +++ /dev/null @@ -1,25 +0,0 @@ -{ "a": // 7 -{ "b": "c", // 19 -"d": { // 25 -"e": "f", // 35 -"g": { // 42 -"h": { // 48 -"i": "j", -"k": "l", -"m": "n", -"o": "p", -"q": "r", -"s": { -"t": "u", -"v": [ -"w", -"x" -] -}, // 138 -"y": "z" // 147 -} // 149 -} // 151 -} // 153 -} // 155 -} // 157 - diff --git a/json_examples/test_depth.json b/json_examples/test_depth.json deleted file mode 100644 index ad2f816..0000000 --- a/json_examples/test_depth.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "key1": "abc", - "key2": { - "key3": "def" - } -} \ No newline at end of file diff --git a/json_examples/test_two_key.json b/json_examples/test_two_key.json deleted file mode 100644 index 437a6c5..0000000 --- a/json_examples/test_two_key.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "key1": "abc", - "key2": "def" -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8f16d6c..d3c324f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use clap::Parser; +use clap::{Parser, Subcommand}; use serde_json::Value; use std::io::Write; use std::path::PathBuf; @@ -6,21 +6,34 @@ use std::path::PathBuf; #[derive(Parser, Debug)] #[command(name = "witness")] struct Args { - /// Path to the JSON file - #[arg(short, long)] - json_file: PathBuf, - - /// Keys to extract (can be specified multiple times) - #[arg(short, long)] - keys: Vec, + #[command(subcommand)] + command: Command, /// Output directory (will be created if it doesn't exist) - #[arg(short, long, default_value = ".")] + #[arg(global = true, short, long, default_value = ".")] output_dir: PathBuf, /// Output filename (will be created if it doesn't exist) - #[arg(short, long, default_value = "output.json")] - filename: String, + #[arg(global = true, short, long, default_value = "output.json")] + output_filename: String, +} + +#[derive(Subcommand, Debug)] +enum Command { + Json { + /// Path to the JSON file + #[arg(short, long)] + input_file: PathBuf, + + /// Keys to extract (can be specified multiple times) + #[arg(short, long)] + keys: Vec, + }, + Http { + /// Path to the HTTP request file + #[arg(short, long)] + input_file: PathBuf, + }, } #[derive(serde::Serialize)] @@ -33,24 +46,30 @@ pub struct Witness { pub fn main() -> Result<(), Box> { let args = Args::parse(); - // Read the JSON file - let data = std::fs::read(&args.json_file)?; - - // Create a map to store keys - let mut keys_map = serde_json::Map::new(); - for (index, key) in args.keys.iter().enumerate() { - keys_map.insert( - format!("key{}", index + 1), - Value::Array( - key.as_bytes() - .iter() - .map(|x| serde_json::json!(x)) - .collect(), - ), - ); - } + let (data, keys_map) = match &args.command { + Command::Json { input_file, keys } => { + let data = std::fs::read(input_file)?; + let mut keys_map = serde_json::Map::new(); + for (index, key) in keys.iter().enumerate() { + keys_map.insert( + format!("key{}", index + 1), + Value::Array( + key.as_bytes() + .iter() + .map(|x| serde_json::json!(x)) + .collect(), + ), + ); + } + (data, keys_map) + } + Command::Http { input_file } => { + let data = std::fs::read(input_file)?; + let keys_map = serde_json::Map::new(); + (data, keys_map) + } + }; - // Create a witness file as `input.json` let witness = Witness { keys: keys_map, data: data.clone(), @@ -60,15 +79,22 @@ pub fn main() -> Result<(), Box> { std::fs::create_dir_all(&args.output_dir)?; } - let output_file = args.output_dir.join(args.filename); + let output_file = args.output_dir.join(args.output_filename); let mut file = std::fs::File::create(output_file)?; file.write_all(serde_json::to_string_pretty(&witness)?.as_bytes())?; // Prepare lines to print let mut lines = Vec::new(); - lines.push(String::from("Key lengths:")); - for (index, key) in args.keys.iter().enumerate() { - lines.push(format!("key{} length: {}", index + 1, key.len())); + match &args.command { + Command::Json { keys, .. } => { + lines.push(String::from("Key lengths:")); + for (index, key) in keys.iter().enumerate() { + lines.push(format!("key{} length: {}", index + 1, key.len())); + } + } + Command::Http { .. } => { + lines.push(String::from("HTTP request processed")); + } } lines.push(format!("Data length: {}", data.len())); From 4c2685977458e6a7f8d6f4275e575eb8c59f26c1 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 27 Aug 2024 14:51:00 -0600 Subject: [PATCH 3/7] basic HTTP language file --- circuits/parser_http/language.circom | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 circuits/parser_http/language.circom diff --git a/circuits/parser_http/language.circom b/circuits/parser_http/language.circom new file mode 100644 index 0000000..709c2f8 --- /dev/null +++ b/circuits/parser_http/language.circom @@ -0,0 +1,21 @@ +// 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 char: `\n` + signal output NEWLINE <== 10; + // - ASCII char: ` ` + signal output SPACE <== 32; + //-Escape-------------------------------------------------------------------------------------// + // - ASCII char: `\` + signal output ESCAPE <== 92; +} \ No newline at end of file From b7d34d8f02e051f29f35538fe02309243ac4ecd6 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 27 Aug 2024 15:29:18 -0600 Subject: [PATCH 4/7] parse request method --- circuits.json | 5 ++ circuits/parser_http/language.circom | 21 --------- circuits/parser_http_request/language.circom | 48 ++++++++++++++++++++ circuits/parser_http_request/machine.circom | 28 ++++++++++++ circuits/parser_http_request/parser.circom | 24 ++++++++++ 5 files changed, 105 insertions(+), 21 deletions(-) delete mode 100644 circuits/parser_http/language.circom create mode 100644 circuits/parser_http_request/language.circom create mode 100644 circuits/parser_http_request/machine.circom create mode 100644 circuits/parser_http_request/parser.circom diff --git a/circuits.json b/circuits.json index 5799800..bd295ac 100644 --- a/circuits.json +++ b/circuits.json @@ -70,5 +70,10 @@ 787, 10 ] + }, + "get_request": { + "file": "parser_http_request/parser", + "template": "Parser", + "params": [158] } } \ No newline at end of file diff --git a/circuits/parser_http/language.circom b/circuits/parser_http/language.circom deleted file mode 100644 index 709c2f8..0000000 --- a/circuits/parser_http/language.circom +++ /dev/null @@ -1,21 +0,0 @@ -// 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 char: `\n` - signal output NEWLINE <== 10; - // - ASCII char: ` ` - signal output SPACE <== 32; - //-Escape-------------------------------------------------------------------------------------// - // - ASCII char: `\` - signal output ESCAPE <== 92; -} \ No newline at end of file diff --git a/circuits/parser_http_request/language.circom b/circuits/parser_http_request/language.circom new file mode 100644 index 0000000..b513d43 --- /dev/null +++ b/circuits/parser_http_request/language.circom @@ -0,0 +1,48 @@ +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 char: `\n` + signal output NEWLINE <== 10; + // - 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; +} \ No newline at end of file diff --git a/circuits/parser_http_request/machine.circom b/circuits/parser_http_request/machine.circom new file mode 100644 index 0000000..ee0cff1 --- /dev/null +++ b/circuits/parser_http_request/machine.circom @@ -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; +} \ No newline at end of file diff --git a/circuits/parser_http_request/parser.circom b/circuits/parser_http_request/parser.circom new file mode 100644 index 0000000..9fd9524 --- /dev/null +++ b/circuits/parser_http_request/parser.circom @@ -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); +} \ No newline at end of file From 9c4ee69c2330047456235986d19781e7ff65199d Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Tue, 27 Aug 2024 15:29:59 -0600 Subject: [PATCH 5/7] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8a5ceb1..3d00468 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ 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 From 98abbfba93de7bd62e936d37fee5816489772992 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 28 Aug 2024 13:25:20 -0600 Subject: [PATCH 6/7] add note on CLRF --- circuits/parser_http_request/language.circom | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/circuits/parser_http_request/language.circom b/circuits/parser_http_request/language.circom index b513d43..a001d86 100644 --- a/circuits/parser_http_request/language.circom +++ b/circuits/parser_http_request/language.circom @@ -13,8 +13,9 @@ template Syntax() { // - ASCII char `"` signal output QUOTE <== 34; //-White_space--------------------------------------------------------------------------------// - // - ASCII char: `\n` - signal output NEWLINE <== 10; + // - 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-------------------------------------------------------------------------------------// From 7a82b5e3b536a4895be3c06627e1c838d76e8bea Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Wed, 28 Aug 2024 13:27:15 -0600 Subject: [PATCH 7/7] Update get_response.http --- examples/http/get_response.http | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/examples/http/get_response.http b/examples/http/get_response.http index 423643b..ac11942 100644 --- a/examples/http/get_response.http +++ b/examples/http/get_response.http @@ -1,7 +1,5 @@ HTTP/1.1 200 OK -Cache-Control: no-cache -Server: libnhttpd -Date: Wed Jul 4 15:32:03 2012 -Connection: Keep-Alive: -Content-Type: application/rdf+xml -Content-Length: 24860 \ No newline at end of file +Content-Type: application/json +Content-Length: 19 + +{"success":"true"} \ No newline at end of file