diff --git a/README.md b/README.md index 3d00468..f6bed74 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,15 @@ ## Repo Structure The repository is currently new and being organized as follows: - - `src/` - - Example Rust code to test against circom circuits. - - Used for doing witness generation - - `circuits/` - - Has current implementation of circuits +- `src/bin`: binaries + - `witness`: Used for doing witness generation + - `codegen`: Used for generating extractor circuits based on input +- `circuits/`: Has current implementation of circuits + - `http`: HTTP parser and extractor + - `json`: JSON parser and extractor + - `utils`: utility circuits + - `test`: circuit tests +- `examples`: reference examples for JSON and HTTP parsers ## Instructions @@ -57,25 +61,94 @@ 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 -``` +## Binaries + +### Rust Example Witness JSON Creation +To generate example input JSON files for the Circom circuits, run: + +```bash 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. + +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: -``` + +```bash 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: -``` +```bash 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`. +### Codegen + +JSON extractor circuit is generated using rust to handle arbitrary keys and array indices. + +Run: +```bash +cargo run --bin codegen -- --help +``` +to get options: +``` +Usage: codegen [OPTIONS] --json-file + +Options: + -j, --json-file Path to the JSON file + -o, --output-filename Output circuit file name [default: extractor] +``` +Takes input 2 arguments: +- `json-file`: input json file. Examples are located in [codegen](./examples/json/test/codegen/) +- `output-filename`: circuit filename to save. Located in [circuits/main](./circuits/main/). If not given, defaults to `extractor.circom`. + +To test an end-to-end JSON extraction proof: +- Run codegen to generate circuits. Replace `value_string` with input filename. + ```bash + cargo run --bin codegen -- --json-file ./examples/json/test/codegen/value_string.json --output-filename value_string + ``` + +- Compile circom circuit using + ``` + circom ./circuits/main/value_string.circom --r1cs --wasm + ``` + +- To use circomkit: add circuit config to [circuits.json](./circuits.json). and input file to [inputs](./inputs/) + +- Generate witness: + ```bash + node build/json_extract_value_string/json_extract_value_string_js/generate_witness inputs/json_extract_value_string/value_string.json build/json_extract_value_string/witness/ + ``` + or generate using circomkit: + ```bash + npx circomkit witness json_extract_value_string value_string + ``` + +- create trusted setup: + ```bash + npx circomkit setup json_extract_value_string + # OR + snarkjs groth16 setup build/json_extract_value_string/json_extract_value_string.r1cs ptau/powersOfTau28_hez_final_14.ptau build/json_extract_value_string/groth16_pkey.zkey + ``` + +- create proof: + ```bash + npx circomkit prove json_extract_value_string value_string + # OR + snarkjs groth16 prove build/json_extract_value_string/groth16_pkey.zkey build/json_extract_value_string/value_string/witness.wtns build/json_extract_value_string/value_string/groth16_proof.json inputs/json_extract_value_string/value_string.json + ``` + +- verify proof: + ```bash + npx circomkit verify json_extract_value_string value_string + # OR + snarkjs groth16 verify build/json_extract_value_string/groth16_vkey.json inputs/json_extract_value_string/value_string.json build/json_extract_value_string/value_string/groth16_proof.json + ``` + ## Testing To test, you can just run ``` diff --git a/circuits.json b/circuits.json index bd295ac..1677d84 100644 --- a/circuits.json +++ b/circuits.json @@ -1,6 +1,6 @@ { "extract": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 157, @@ -8,7 +8,7 @@ ] }, "value_string": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 12, @@ -16,7 +16,7 @@ ] }, "value_number": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 12, @@ -24,7 +24,7 @@ ] }, "value_array": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 18, @@ -32,7 +32,7 @@ ] }, "value_array_nested": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 24, @@ -40,7 +40,7 @@ ] }, "value_array_object": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 25, @@ -48,7 +48,7 @@ ] }, "value_array_object_array": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 31, @@ -56,7 +56,7 @@ ] }, "value_object": { - "file": "parser_json/parser", + "file": "json/parser/parser", "template": "Parser", "params": [ 21, @@ -71,9 +71,22 @@ 10 ] }, - "get_request": { - "file": "parser_http_request/parser", + "http_get_request": { + "file": "http/http_request/parser", "template": "Parser", - "params": [158] + "params": [ + 158 + ] + }, + "json_extract_value_string": { + "file": "main/value_string", + "template": "ExtractStringValue", + "params": [ + 12, + 1, + 1, + 0, + 1 + ] } } \ No newline at end of file diff --git a/circuits/test/common/index.ts b/circuits/test/common/index.ts index 6206f23..1169a78 100644 --- a/circuits/test/common/index.ts +++ b/circuits/test/common/index.ts @@ -25,7 +25,7 @@ export function generateDescription(input: any): string { .join(", "); } -export function readInputFile(filename: string, key: any[]): [number[], number[][], number[]] { +export function readJSONInputFile(filename: string, key: any[]): [number[], number[][], number[]] { const valueStringPath = join(__dirname, "..", "..", "..", "examples", "json", "test", filename); let input: number[] = []; diff --git a/circuits/test/json/extractor/extractor.test.ts b/circuits/test/json/extractor/extractor.test.ts index 2a693ec..bc13620 100644 --- a/circuits/test/json/extractor/extractor.test.ts +++ b/circuits/test/json/extractor/extractor.test.ts @@ -1,4 +1,4 @@ -import { circomkit, WitnessTester, readInputFile } from "../../common"; +import { circomkit, WitnessTester, readJSONInputFile } from "../../common"; import { join } from "path"; import { spawn } from "child_process"; @@ -32,8 +32,12 @@ describe("ExtractValue", async () => { it("value_string: {\"a\": \"b\"}", async () => { let filename = "value_string"; + + // generate extractor circuit using codegen await executeCodegen(`${filename}.json`, filename); - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["k"]); + + // read JSON input file into bytes + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["k"]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -42,6 +46,7 @@ describe("ExtractValue", async () => { }); console.log("#constraints:", await circuit.getConstraintCount()); + // match circuit output to original JSON value await circuit.expectPass({ data: input, key1: keyUnicode, }, { @@ -52,7 +57,7 @@ describe("ExtractValue", async () => { it("two_keys: {\"key1\": \"abc\", \"key2\": \"def\" }", async () => { let filename = "two_keys" await executeCodegen(`${filename}.json`, filename); - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["key2"]); + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["key2"]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -67,7 +72,7 @@ describe("ExtractValue", async () => { it("value_number: {\"k\": 69 }", async () => { let filename = "value_number"; await executeCodegen(`${filename}.json`, filename); - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["k"]); + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["k"]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -86,7 +91,7 @@ describe("ExtractValue", async () => { await executeCodegen(`${filename}.json`, filename); for (let i = 0; i < 4; i++) { - let [input, keyUnicode, output] = readInputFile("value_array.json", ["b", i]); + let [input, keyUnicode, output] = readJSONInputFile("value_array.json", ["b", i]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -104,7 +109,7 @@ describe("ExtractValue", async () => { await executeCodegen(`${filename}.json`, filename); for (let i = 0; i < 4; i++) { - let [input, keyUnicode, output] = readInputFile("value_array.json", ["k", i]); + let [input, keyUnicode, output] = readJSONInputFile("value_array.json", ["k", i]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -123,7 +128,7 @@ describe("ExtractValue", async () => { await executeCodegen(`${filename}.json`, filename); let index_0 = 1; let index_1 = 0; - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["a", index_0, index_1]); + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a", index_0, index_1]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -147,7 +152,7 @@ describe("ExtractValueMultiDepth", () => { await executeCodegen(`${filename}.json`, filename); - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["e", "e"]); + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["e", "e"]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, @@ -158,7 +163,7 @@ describe("ExtractValueMultiDepth", () => { await circuit.expectPass({ data: input, key1: keyUnicode[0], key2: keyUnicode[1] }, { value: output }); - let [input1, keyUnicode1, output1] = readInputFile("value_object.json", ["e", "f"]); + let [input1, keyUnicode1, output1] = readJSONInputFile("value_object.json", ["e", "f"]); await circuit.expectPass({ data: input1, key1: keyUnicode1[0], key2: keyUnicode1[1] }, { value: output1 }); }); @@ -175,7 +180,7 @@ describe("ExtractValueArrayObject", () => { let index_0 = 0; let index_1 = 0; - let [input, keyUnicode, output] = readInputFile(`${filename}.json`, ["a", index_0, "b", index_1]); + let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a", index_0, "b", index_1]); circuit = await circomkit.WitnessTester(`Extract`, { file: `circuits/main/${filename}`, diff --git a/circuits/test/json/extractor/interpreter.test.ts b/circuits/test/json/extractor/interpreter.test.ts index 9ee8953..cb2bfd6 100644 --- a/circuits/test/json/extractor/interpreter.test.ts +++ b/circuits/test/json/extractor/interpreter.test.ts @@ -1,4 +1,4 @@ -import { circomkit, WitnessTester, generateDescription, readInputFile } from "../../common"; +import { circomkit, WitnessTester, generateDescription, readJSONInputFile } from "../../common"; import { PoseidonModular } from "../../common/poseidon"; describe("Interpreter", async () => { @@ -283,7 +283,7 @@ describe("Interpreter", async () => { }); } - let input = readInputFile("value_array_object.json", ["a"]); + let input = readJSONInputFile("value_array_object.json", ["a"]); const concatenatedInput = input[1][0].concat(input[0]); const hashResult = PoseidonModular(concatenatedInput); @@ -324,7 +324,7 @@ describe("Interpreter", async () => { }); } - let input = readInputFile("value_array_object.json", ["a", 0, "b", 0]); + let input = readJSONInputFile("value_array_object.json", ["a", 0, "b", 0]); const concatenatedInput = input[1][0].concat(input[0]); const hashResult = PoseidonModular(concatenatedInput); diff --git a/docs/json.md b/docs/json.md new file mode 100644 index 0000000..3f77d7c --- /dev/null +++ b/docs/json.md @@ -0,0 +1,175 @@ +# JSON extractor + +Extractor module provides circuits to generate proofs of arbitrary values in a JSON file. To achieve this, proof generation is broken into following components: +- [parser](../circuits/json/parser/): state parser based on a stack machine +- [interpreter](../circuits/json/interpreter.circom): high-level interpretation of JSON state +- [codegen](../src/bin/codegen.rs): extractor circuit generation +- [extractor](../circuits/main/extractor.circom): extracting value for a specific key inside a JSON + +## Parser +Parser is divided into three files: +- [Language](../circuits/json/parser/language.circom): JSON language syntax +- [Parser](../circuits/json/parser/parser.circom): initialises the parser and parse individual bytes +- [Machine](../circuits/json/parser/machine.circom): stack machine responsible for updating state + +State of JSON parser consists of: +- `stack` with a maximum `MAX_STACK_HEIGHT` argument +- `parsing_string` +- `parsing_number` + +Let's take a simple [example](../examples/json/test/value_string.json): `{ "k": "v" }`. Parser initialises the stack with `[0, 0]` and starts iterating through each byte one-by-one. + +1. `0`: detects `START_BRACKET: {`. so, we're inside a key and updates stack to `[1, 0]` +2. `3`: detects a `QUOTE:"` and toggles `parsing_string` to `1` +3. `4`: detects another `QUOTE` and toggles `parsing_string` back to `0` +4. `5`: detects `COLON` and updates stack to `[1, 1]` which means we're now inside a value +5. `7`: detects a `QUOTE` again and toggles `parsing_string` which is toggled back on `9` +6. `11`: detects `CLOSING_BRACKET: }` and resets stack back to `[0, 0]` + +``` +State[ 0 ].byte = 123 +State[ 0 ].stack[ 0 ] = [ 1 ][ 0 ] +State[ 0 ].parsing_string = 0 +State[ 0 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 1 ].byte = 32 +State[ 1 ].stack[ 0 ] = [ 1 ][ 0 ] +State[ 1 ].parsing_string = 0 +State[ 1 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 2 ].byte = 34 +State[ 2 ].stack[ 0 ] = [ 1 ][ 0 ] +State[ 2 ].parsing_string = 1 +State[ 2 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 3 ].byte = 107 +State[ 3 ].stack[ 0 ] = [ 1 ][ 0 ] +State[ 3 ].parsing_string = 1 +State[ 3 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 4 ].byte = 34 +State[ 4 ].stack[ 0 ] = [ 1 ][ 0 ] +State[ 4 ].parsing_string = 0 +State[ 4 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 5 ].byte = 58 +State[ 5 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 5 ].parsing_string = 0 +State[ 5 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 6 ].byte = 32 +State[ 6 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 6 ].parsing_string = 0 +State[ 6 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 7 ].byte = 34 +State[ 7 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 7 ].parsing_string = 1 +State[ 7 ].parsing_number = 0 +mask 34 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 8 ].byte = 118 +State[ 8 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 8 ].parsing_string = 1 +State[ 8 ].parsing_number = 0 +mask 118 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 9 ].byte = 34 +State[ 9 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 9 ].parsing_string = 0 +State[ 9 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 10 ].byte = 32 +State[ 10 ].stack[ 0 ] = [ 1 ][ 1 ] +State[ 10 ].parsing_string = 0 +State[ 10 ].parsing_number = 0 +mask 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +State[ 11 ].stack[ 0 ] = [ 0 ][ 0 ] +State[ 11 ].parsing_string = 0 +State[ 11 ].parsing_number = 0 +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +value_starting_index 7 +value[ 0 ]= 118 +``` + +Logic for parser: +- Iterate through each byte. +- Determine current byte token, and form instruction. + - determine what is the current byte in signals: start brace, end brace, start bracket, end bracket, colon, comma, number, quote, other (whitespace) + - create an instruction by multiplying arrays together +- form a state mask based on current state +- multiply instruction and mask together to calculate whether reading or writing value to stack. +- rewrite stack using new instruction + - stack[0] can change when pushing (read start brace or bracket) / popping (read end brace or bracket) + - stack[1] can change when readColon / readComma + +Let's deep dive into interpreter and extractor. + +## Interpreter +Interpreter builds high-level circuits on top of stack to understand state better. It provides following templates: +- `InsideKey` +- `InsideValue` & `InsideValueAtDepth` +- `InsideArrayIndex` & `InsideArrayIndexAtDepth` +- `NextKVPair` & `NextKVPairAtDepth` +- `KeyMatch` & `KeyMatchAtDepth` + +## Codegen +To handle arbitrary depth JSON key, we need to generate circuits on-the-fly using some metadata. + +```json +{ + "keys": [ + "a" + ], + "value_type": "string" +} +``` + +Each new key in `keys` is associated with depth in parser stack, i.e. key `a` has depth `0`, and the value type of `a` is a `string`. +Using this, a rust program generates circuit that can extract any key at depth 0 (and not just key `a`) whose value type is a string. + +## Extractor +To extract a key at specific depth and value type, we provide + +arguments: +- `DATA_BYTES`: data length in bytes +- `MAX_STACK_HEIGHT`: maximum stack height possible during parsing of `data`. Equal to maximum open brackets `{, [` in data. +- `keyLen{i}`: ith key length in bytes, if key is a string +- `index{i}`: ith key array index +- `depth{i}`: ith key's stack depth +- `maxValueLen`: maximum value length + +inputs: +- `data`: data in bytes array of `DATA_BYTES` length +- `key{i}`: key i in bytes array of `keyLen{i}` length + +output: +- `value`: value of the specified key + +Extractor performs following operations: +- parse data byte-by-byte using parser +- use interpreter to gather more information on current state, i.e. whether we're parsing key or value +- if `parsing_key`, then it matches each key in `is_key{i}_match` signal +- if `parsing_value`, then it checks whether we're inside correct values at each depth, i.e. + - if the key looks like `a.0.b.0` then, value of stack at depth `0` should be `[1, 1]`, and depth `1` should be `[2, 0]`, and so on. +- if the key matches, then we need to propogate this result to the value of that key. + - We use interpreter's `NextKVPair` template to determine when we start parsing next key pair again in `is_next_pair_at_depth{i}` +- In previous example, + - key match (`byte = 107`) happened at state 3. so we toggle `is_key1_match_for_value[3]` true. + - At state 4, `is_key1_match[4]` will return false, but, since we're not parsing next key pair again, we want `is_key1_match_for_value[4]=true` as well. + - So, we just use previous index's `is_key1_match_for_value` value, i.e. `is_key1_match_for_value[4] = is_key1_match_for_value[3] * is_next_pair[4]` + - as soon as we hit next pair, we toggle this bit again to 0, and wait for key match again. +- To extract the value, we create a `mask` around that value. + - `mask[i] = data[i] * parsing_value[i] * is_value_match[i]`, i.e. we're inside the correct value and the key matched for this value. +- Then, we just shift `data` by `value_starting_bytes` to the left and truncate `data` length to `maxValueLen`. + +We encourage you to look at [tests](../circuits/test/json/), if you need deeper understanding of [examples](../examples/json/test/). \ No newline at end of file diff --git a/inputs/test_extract_sambhav/input.json b/inputs/test_extract_sambhav/input.json deleted file mode 100644 index 9e6cbba..0000000 --- a/inputs/test_extract_sambhav/input.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "key": [ - 107, - 101, - 121, - 49 - ], - "data": [ - 123, - 10, - 32, - 32, - 32, - 32, - 34, - 101, - 120, - 116, - 114, - 97, - 99, - 116, - 34, - 58, - 32, - 123, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 102, - 105, - 108, - 101, - 34, - 58, - 32, - 34, - 101, - 120, - 116, - 114, - 97, - 99, - 116, - 34, - 44, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 116, - 101, - 109, - 112, - 108, - 97, - 116, - 101, - 34, - 58, - 32, - 34, - 69, - 120, - 116, - 114, - 97, - 99, - 116, - 34, - 44, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 112, - 97, - 114, - 97, - 109, - 115, - 34, - 58, - 32, - 34, - 34, - 10, - 32, - 32, - 32, - 32, - 125, - 10, - 125 - ] -} \ No newline at end of file diff --git a/src/bin/codegen.rs b/src/bin/codegen.rs index d9ab4d2..5024ceb 100644 --- a/src/bin/codegen.rs +++ b/src/bin/codegen.rs @@ -66,10 +66,10 @@ fn extract_string(data: Data, circuit_buffer: &mut String) { signal value_starting_index[DATA_BYTES]; "#; - // value_starting_index <== ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, keyLen2, depth2, index3, depth3, index4, depth4, maxValueLen)(data, key1, key2); + // value_starting_index <== ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, keyLen2, depth2, index3, depth3, index4, depth4, maxValueLen)(data, key1, key2); { *circuit_buffer += - " value_starting_index <== ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, "; + " value_starting_index <== ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, "; for (i, key) in data.keys.iter().enumerate() { match key { Key::String(_) => *circuit_buffer += &format!("keyLen{}, depth{}, ", i + 1, i + 1), @@ -127,10 +127,10 @@ fn extract_number(data: Data, circuit_buffer: &mut String) { signal value_starting_index[DATA_BYTES]; "#; - // value_starting_index <== ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, keyLen2, depth2, index3, depth3, index4, depth4, maxValueLen)(data, key1, key2); + // value_starting_index <== ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, keyLen2, depth2, index3, depth3, index4, depth4, maxValueLen)(data, key1, key2); { *circuit_buffer += - " value_starting_index <== ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, "; + " value_starting_index <== ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, "; for (i, key) in data.keys.iter().enumerate() { match key { Key::String(_) => *circuit_buffer += &format!("keyLen{}, depth{}, ", i + 1, i + 1), @@ -176,9 +176,9 @@ fn parse_json_request( circuit_buffer += PRAGMA; circuit_buffer += "include \"../json/interpreter.circom\";\n\n"; - // template ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, index2, depth2, keyLen3, depth3, index4, depth4, maxValueLen) { + // template ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, keyLen1, depth1, index2, depth2, keyLen3, depth3, index4, depth4, maxValueLen) { { - circuit_buffer += "template ExtractValue2(DATA_BYTES, MAX_STACK_HEIGHT, "; + circuit_buffer += "template ExtractValue(DATA_BYTES, MAX_STACK_HEIGHT, "; for (i, key) in data.keys.iter().enumerate() { match key { Key::String(_) => circuit_buffer += &format!("keyLen{}, depth{}, ", i + 1, i + 1),