diff --git a/circuits/json/interpreter.circom b/circuits/json/interpreter.circom index 82db99d..3ccd7ad 100644 --- a/circuits/json/interpreter.circom +++ b/circuits/json/interpreter.circom @@ -393,7 +393,10 @@ template KeyMatchAtDepth(dataLen, n, keyLen, depth) { signal output out <== substring_match * is_parsing_correct_key_at_depth; } +// TODO: Not checking start of key is quote since that is handled by `parsing_key`? template MatchPaddedKey(n) { + // TODO: If key is not padded at all, then `in[1]` will not contain an end quote. + // Perhaps we modify this to handle that, or just always pad the key at least once. signal input in[2][n]; signal input keyLen; signal output out; diff --git a/circuits/json/nivc/extractor.circom b/circuits/json/nivc/extractor.circom index ed7db26..aadb436 100644 --- a/circuits/json/nivc/extractor.circom +++ b/circuits/json/nivc/extractor.circom @@ -3,9 +3,16 @@ pragma circom 2.1.9; include "circomlib/circuits/gates.circom"; include "@zk-email/circuits/utils/array.circom"; -template MaskExtractFinal(TOTAL_BYTES, DATA_BYTES, maxValueLen) { - signal input step_in[TOTAL_BYTES + 1]; - signal output step_out[TOTAL_BYTES + 1]; +template MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH) { + // ------------------------------------------------------------------------------------------------------------------ // + // ~~ Set sizes at compile time ~~ + // Total number of variables in the parser for each byte of data + assert(MAX_STACK_HEIGHT >= 2); + var PER_ITERATION_DATA_LENGTH = MAX_STACK_HEIGHT * 2 + 2; + var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1) + 1; + // ------------------------------------------------------------------------------------------------------------------ // + signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; + signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; signal is_zero_mask[DATA_BYTES]; signal is_prev_starting_index[DATA_BYTES]; @@ -19,21 +26,22 @@ template MaskExtractFinal(TOTAL_BYTES, DATA_BYTES, maxValueLen) { value_starting_index[0] <== 0; is_prev_starting_index[0] <== 0; is_zero_mask[0] <== IsZero()(step_in[0]); - for (var i=1 ; i(join(__dirname, "..", "nivc/nivc_parse.j let nivc_extract_key0 = readJsonFile(join(__dirname, "..", "nivc/nivc_extract_key0.json")); let nivc_extract_key1 = readJsonFile(join(__dirname, "..", "nivc/nivc_extract_key1.json")); let nivc_extract_arr = readJsonFile(join(__dirname, "..", "nivc/nivc_extract_arr.json")); +let nivc_extract_key2 = readJsonFile(join(__dirname, "..", "nivc/nivc_extract_key2.json")); let nivc_extract_key3 = readJsonFile(join(__dirname, "..", "nivc/nivc_extract_key3.json")); describe("JsonParseNIVC", async () => { @@ -70,7 +71,7 @@ describe("JsonParseNIVC", async () => { function generatePassCase(input: any, expected: any, desc: string) { const description = generateDescription(input); - it(`(valid) witness: ${description} ${desc}`, async () => { + it(`(valid) witness: ${desc}`, async () => { await circuit.expectPass(input, expected); }); @@ -87,7 +88,7 @@ describe("JsonMaskObjectNIVC", async () => { let DATA_BYTES = 202; let MAX_STACK_HEIGHT = 5; - let MAX_KEY_LENGTH = 7; + let MAX_KEY_LENGTH = 8; let step_out: bigint[] = []; before(async () => { @@ -105,28 +106,28 @@ describe("JsonMaskObjectNIVC", async () => { it(`(valid) witness: ${desc}`, async () => { // console.log(JSON.stringify(await circuit.compute(input, ["step_out"]))) let wit = await circuit.calculateWitness(input); - console.log("wit", wit.slice(0, 100)); + // console.log("wit", wit.slice(0, 100)); // step_out = wit; - // await circuit.expectPass(input, expected); + await circuit.expectPass(input, expected); }); } - // let key0 = [100, 97, 116, 97, 0, 0, 0]; // "data" - // let key0Len = 4; - // generatePassCase({ step_in: nivc_parse.step_out, key: key0, keyLen: key0Len }, { step_out: nivc_extract_key0.step_out }, "masking json object at depth 0"); + let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data" + let key0Len = 4; + generatePassCase({ step_in: nivc_parse.step_out, key: key0, keyLen: key0Len }, { step_out: nivc_extract_key0.step_out }, "masking json object at depth 0"); - let key1 = [105, 116, 101, 109, 115, 0, 0]; // "items" + let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items" let key1Len = 5; - generatePassCase({ step_in: nivc_extract_key0.step_out, key: key1, keyLen: key1Len }, { step_out: nivc_extract_key1.step_out }, "masking json object at depth 0"); + generatePassCase({ step_in: nivc_extract_key0.step_out, key: key1, keyLen: key1Len }, { step_out: nivc_extract_key1.step_out }, "masking json object at depth 1"); // Ran after doing arr masking - // let key2 = [112, 114, 111, 102, 105, 108, 101]; // "profile" - // let key2Len = 7; - // generatePassCase({ step_in: nivc_extract_arr.step_out, key: key2, keyLen: key2Len }, { step_out: nivc_extract_key1.step_out }, "masking json object at depth 0"); + let key2 = [112, 114, 111, 102, 105, 108, 101, 0]; // "profile" + let key2Len = 7; + generatePassCase({ step_in: nivc_extract_arr.step_out, key: key2, keyLen: key2Len }, { step_out: nivc_extract_key2.step_out }, "masking json object at depth 3"); - // let key3 = [110, 97, 109, 101, 0, 0, 0]; // "name" - // let key3Len = 4; - // generatePassCase({ step_in: nivc_extract_key3.step_out, key: key3, keyLen: key3Len }, {}, "masking json at depth 4"); + let key3 = [110, 97, 109, 101, 0, 0, 0, 0]; // "name" + let key3Len = 4; + generatePassCase({ step_in: nivc_extract_key2.step_out, key: key3, keyLen: key3Len }, { step_out: nivc_extract_key3.step_out }, "masking json object at depth 4"); }); describe("JsonMaskArrayIndexNIVC", async () => { @@ -147,12 +148,41 @@ describe("JsonMaskArrayIndexNIVC", async () => { function generatePassCase(input: any, expected: any, desc: string) { const description = generateDescription(input); - it(`(valid) witness: ${description} ${desc}`, async () => { - console.log(JSON.stringify(await circuit.compute(input, ["step_out"]))) + it(`(valid) witness: ${desc}`, async () => { + // console.log(JSON.stringify(await circuit.compute(input, ["step_out"]))) await circuit.expectPass(input, expected); }); } let index = 0; - generatePassCase({ step_in: nivc_extract_key1.step_out, index: index }, { step_out: nivc_extract_arr.step_out }, "masking json object at depth 0"); -}); \ No newline at end of file + generatePassCase({ step_in: nivc_extract_key1.step_out, index: index }, { step_out: nivc_extract_arr.step_out }, "masking json array index at depth 2"); +}); + + +describe("JsonExtractNIVC", async () => { + let circuit: WitnessTester<["step_in"], ["step_out"]>; + + let DATA_BYTES = 202; + let MAX_STACK_HEIGHT = 5; + + before(async () => { + circuit = await circomkit.WitnessTester(`JsonMaskExtractFinal`, { + file: "json/nivc/extractor", + template: "MaskExtractFinal", + params: [DATA_BYTES, MAX_STACK_HEIGHT, 14], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + }); + + function generatePassCase(input: any, expected: any, desc: string) { + const description = generateDescription(input); + + it(`(valid) witness: ${desc}`, async () => { + // console.log(JSON.stringify(await circuit.compute(input, ["step_out", "value"]))) + await circuit.expectPass(input, expected); + }); + } + + + generatePassCase({ step_in: nivc_extract_key3.step_out }, {}, "masking json at depth 4"); +}); diff --git a/circuits/test/json/nivc/nivc_extract_key0.json b/circuits/test/json/nivc/nivc_extract_key0.json index d5f36aa..dbd4304 100644 --- a/circuits/test/json/nivc/nivc_extract_key0.json +++ b/circuits/test/json/nivc/nivc_extract_key0.json @@ -195,10 +195,10 @@ 93, 13, 10, - 0, - 0, - 0, - 0, + 32, + 32, + 32, + 125, 0, 0, 0, diff --git a/circuits/test/json/nivc/nivc_extract_key1.json b/circuits/test/json/nivc/nivc_extract_key1.json index 4d49a93..7d787ad 100644 --- a/circuits/test/json/nivc/nivc_extract_key1.json +++ b/circuits/test/json/nivc/nivc_extract_key1.json @@ -31,8 +31,8 @@ 0, 0, 0, - 58, - 32, + 0, + 0, 91, 13, 10, @@ -193,8 +193,8 @@ 32, 32, 93, - 13, - 10, + 0, + 0, 0, 0, 0, diff --git a/circuits/test/json/nivc/nivc_extract_key2.json b/circuits/test/json/nivc/nivc_extract_key2.json index ae19f04..09d1b80 100644 --- a/circuits/test/json/nivc/nivc_extract_key2.json +++ b/circuits/test/json/nivc/nivc_extract_key2.json @@ -110,65 +110,65 @@ 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, - 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, + 123, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 34, + 110, + 97, + 109, + 101, + 34, + 58, + 32, + 34, + 84, + 97, + 121, + 108, + 111, + 114, + 32, + 83, + 119, + 105, + 102, + 116, + 34, + 13, + 10, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 32, + 125, 0, 0, 0, diff --git a/circuits/test/json/nivc/nivc_extract_key3.json b/circuits/test/json/nivc/nivc_extract_key3.json index 4dbe2ac..2282500 100644 --- a/circuits/test/json/nivc/nivc_extract_key3.json +++ b/circuits/test/json/nivc/nivc_extract_key3.json @@ -108,35 +108,35 @@ 0, 0, 0, - 58, - 32, - 123, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 34, - 110, - 97, - 109, - 101, - 34, - 58, - 32, + 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, 34, 84, 97, @@ -151,37 +151,37 @@ 102, 116, 34, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 125, - 13, - 10, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, - 32, + 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, 0, 0, @@ -2626,6 +2626,6 @@ 0, 0, 0, - 4 + 5 ] } \ No newline at end of file