From 10c9c0743c8226a18db2ca2bd491ba368df41742 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 10:22:16 +0700 Subject: [PATCH 01/21] added test/http/locker.test.ts --- circuits/test/http/locker.test.ts | 136 ++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 circuits/test/http/locker.test.ts diff --git a/circuits/test/http/locker.test.ts b/circuits/test/http/locker.test.ts new file mode 100644 index 0000000..34f32be --- /dev/null +++ b/circuits/test/http/locker.test.ts @@ -0,0 +1,136 @@ +import { circomkit, WitnessTester, generateDescription, toByte } from "../common"; +import { readHTTPInputFile } from "../common/http"; + +describe("HTTP :: Locker :: Request Line", async () => { + let circuit: WitnessTester<["data", "beginning", "middle", "final"], []>; + + function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { + const description = generateDescription(input); + + it(`(valid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockStartLine`, { + file: "http/locker", + template: "LockStartLine", + params: [input.length, beginning.length, middle.length, final.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass({ data: input, beginning: beginning, middle: middle, final: final }, {}); + }); + } + + function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { + const description = generateDescription(input); + + it(`(invalid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockStartLine`, { + file: "http/locker", + template: "LockStartLine", + params: [input.length, beginning.length, middle.length, final.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectFail({ data: input, beginning: beginning, middle: middle, final: final }); + }); + } + + describe("GET", async () => { + let parsedHttp = readHTTPInputFile("get_request.http"); + generatePassCase(parsedHttp.input, toByte("GET"), toByte("/api"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("POST"), toByte("/api"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("GET"), toByte("/"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("GET"), toByte("/api"), toByte("HTTP"), ""); + }); + + describe("POST", async () => { + let parsedHttp = readHTTPInputFile("post_request.http"); + generatePassCase(parsedHttp.input, toByte("POST"), toByte("/contact_form.php"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("GET"), toByte("/contact_form.php"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("POST"), toByte("/"), toByte("HTTP/1.1"), ""); + generateFailCase(parsedHttp.input.slice(0), toByte("POST"), toByte("/contact_form.php"), toByte("HTTP"), ""); + }); +}); + +describe("HTTP :: Locker :: Status Line", async () => { + let circuit: WitnessTester<["data", "beginning", "middle", "final"], []>; + + function generatePassCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { + const description = generateDescription(input); + + it(`(valid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockStartLine`, { + file: "http/locker", + template: "LockStartLine", + params: [input.length, beginning.length, middle.length, final.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass({ data: input, beginning: beginning, middle: middle, final: final }, {}); + }); + } + + function generateFailCase(input: number[], beginning: number[], middle: number[], final: number[], desc: string) { + const description = generateDescription(input); + + it(`(invalid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockStartLine`, { + file: "http/locker", + template: "LockStartLine", + params: [input.length, beginning.length, middle.length, final.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectFail({ data: input, beginning: beginning, middle: middle, final: final }); + }); + } + + describe("GET", async () => { + let parsedHttp = readHTTPInputFile("get_response.http"); + generatePassCase(parsedHttp.input, toByte("HTTP/1.1"), toByte("200"), toByte("OK"), ""); + generateFailCase(parsedHttp.input, toByte("HTTP"), toByte("200"), toByte("OK"), ""); + generateFailCase(parsedHttp.input, toByte("HTTP/1.1"), toByte("404"), toByte("OK"), ""); + generateFailCase(parsedHttp.input, toByte("HTTP/1.1"), toByte("200"), toByte("Not Found"), ""); + }); +}); + +describe("HTTP :: Locker :: Header", async () => { + let circuit: WitnessTester<["data", "header", "value"], []>; + + function generatePassCase(input: number[], header: number[], value: number[], desc: string) { + const description = generateDescription(input); + + it(`(valid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockHeader`, { + file: "http/locker", + template: "LockHeader", + params: [input.length, header.length, value.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectPass({ data: input, header: header, value: value }, {}); + }); + } + + function generateFailCase(input: number[], header: number[], value: number[], desc: string) { + const description = generateDescription(input); + + it(`(invalid) witness: ${description} ${desc}`, async () => { + circuit = await circomkit.WitnessTester(`LockHeader`, { + file: "http/locker", + template: "LockHeader", + params: [input.length, header.length, value.length], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + + await circuit.expectFail({ data: input, header: header, value: value }); + }); + } + + describe("GET", async () => { + let parsedHttp = readHTTPInputFile("get_request.http"); + generatePassCase(parsedHttp.input, toByte("Host"), toByte("localhost"), ""); + generateFailCase(parsedHttp.input, toByte("Accept"), toByte("localhost"), ""); + generateFailCase(parsedHttp.input, toByte("Host"), toByte("venmo.com"), ""); + generateFailCase(parsedHttp.input, toByte("Connection"), toByte("keep-alive"), ""); + }); +}); \ No newline at end of file From cf2b7f2e91b50daeda3f148e331a730e78abcb0f Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 11:23:54 +0700 Subject: [PATCH 02/21] use updated circuits local paths. All compile --- circuits/aes-gctr-nivc.circom | 1 - circuits/extract_value.circom | 34 +---- circuits/http_body_mask.circom | 34 +---- circuits/http_lock_header.circom | 86 +----------- .../http_parse_and_lock_start_line.circom | 125 +----------------- circuits/json/nivc/extractor.circom | 4 +- circuits/json_mask_array_index.circom | 70 +--------- circuits/json_mask_object.circom | 109 +-------------- circuits/json_parse.circom | 58 +------- package-lock.json | 97 +++++++------- package.json | 6 +- 11 files changed, 68 insertions(+), 556 deletions(-) diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom index 7886f37..2ec7580 100644 --- a/circuits/aes-gctr-nivc.circom +++ b/circuits/aes-gctr-nivc.circom @@ -2,6 +2,5 @@ pragma circom 2.1.9; include "aes-gcm/nivc/aes-gctr-nivc.circom"; -// Note(WJ 2024-10-31): I put this here like this because i have tests i wanted to include for this component // the circomkit tests become unhappy when there is a main. component main { public [step_in] } = AESGCTRFOLD(48); \ No newline at end of file diff --git a/circuits/extract_value.circom b/circuits/extract_value.circom index 3a492ab..8e3906b 100644 --- a/circuits/extract_value.circom +++ b/circuits/extract_value.circom @@ -1,35 +1,5 @@ pragma circom 2.1.9; -include "circomlib/circuits/gates.circom"; -include "@zk-email/circuits/utils/array.circom"; +include "json/nivc/extractor.circom"; -template MaskExtractFinal(TOTAL_BYTES, maxValueLen) { - signal input step_in[TOTAL_BYTES]; - signal output step_out[TOTAL_BYTES]; - - signal is_zero_mask[TOTAL_BYTES]; - signal is_prev_starting_index[TOTAL_BYTES]; - signal value_starting_index[TOTAL_BYTES]; - - value_starting_index[0] <== 0; - is_prev_starting_index[0] <== 0; - is_zero_mask[0] <== IsZero()(step_in[0]); - for (var i=1 ; i var TOTAL_BYTES = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); // data + parser vars - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (HttpParseAndLockStartLine or HTTPLockHeader) - signal input step_in[TOTAL_BYTES]; - - signal data[DATA_BYTES]; - signal parsing_body[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - parsing_body[i] <== step_in[DATA_BYTES + i * 5 + 4]; - } - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Write out to next NIVC step - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - step_out[i] <== data[i] * parsing_body[i]; - } - // Write out padded with zeros - for (var i = DATA_BYTES ; i < TOTAL_BYTES ; i++) { - step_out[i] <== 0; - } -} +include "http/nivc/body_mask.circom"; component main { public [step_in] } = HTTPMaskBodyNIVC(4160, 320); diff --git a/circuits/http_lock_header.circom b/circuits/http_lock_header.circom index 46a55f0..c81aa82 100644 --- a/circuits/http_lock_header.circom +++ b/circuits/http_lock_header.circom @@ -1,87 +1,7 @@ pragma circom 2.1.9; -include "parser-attestor/circuits/http/interpreter.circom"; -include "parser-attestor/circuits/utils/array.circom"; +include "http/nivc/lock_header.circom"; -template LockHeader(TOTAL_BYTES, DATA_BYTES, headerNameLen, headerValueLen) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ Set sizes at compile time ~~ - // Total number of variables in the parser for each byte of data - var PER_ITERATION_DATA_LENGTH = 5; - var TOTAL_BYTES_USED = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); // data + parser vars - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (HttpParseAndLockStartLine or HTTPLockHeader) - signal input step_in[TOTAL_BYTES]; - - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } - - signal input header[headerNameLen]; - signal input value[headerValueLen]; - - component headerNameLocation = FirstStringMatch(DATA_BYTES, headerNameLen); - headerNameLocation.data <== data; - headerNameLocation.key <== header; - - component headerFieldNameValueMatch; - headerFieldNameValueMatch = HeaderFieldNameValueMatch(DATA_BYTES, headerNameLen, headerValueLen); - headerFieldNameValueMatch.data <== data; - headerFieldNameValueMatch.headerName <== header; - headerFieldNameValueMatch.headerValue <== value; - headerFieldNameValueMatch.index <== headerNameLocation.position; - - // TODO: Make this assert we are parsing header!!! - // This is the assertion that we have locked down the correct header - headerFieldNameValueMatch.out === 1; - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Write out to next NIVC step - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - // add plaintext http input to step_out - step_out[i] <== step_in[i]; - - // add parser state - step_out[DATA_BYTES + i * 5] <== step_in[DATA_BYTES + i * 5]; - step_out[DATA_BYTES + i * 5 + 1] <== step_in[DATA_BYTES + i * 5 + 1]; - step_out[DATA_BYTES + i * 5 + 2] <== step_in[DATA_BYTES + i * 5 + 2]; - step_out[DATA_BYTES + i * 5 + 3] <== step_in[DATA_BYTES + i * 5 + 3]; - step_out[DATA_BYTES + i * 5 + 4] <== step_in[DATA_BYTES + i * 5 + 4]; - } - // Pad remaining with zeros - for (var i = TOTAL_BYTES_USED ; i < TOTAL_BYTES ; i++ ) { - step_out[i] <== 0; - } -} - -// TODO: Handrolled template that I haven't tested YOLO. -template FirstStringMatch(dataLen, keyLen) { - signal input data[dataLen]; - signal input key[keyLen]; - signal output position; - - var matched = 0; - var counter = 0; - component stringMatch[dataLen - keyLen]; - component hasMatched[dataLen - keyLen]; - for (var idx = 0 ; idx < dataLen - keyLen ; idx++) { - stringMatch[idx] = IsEqualArray(keyLen); - stringMatch[idx].in[0] <== key; - for (var key_idx = 0 ; key_idx < keyLen ; key_idx++) { - stringMatch[idx].in[1][key_idx] <== data[idx + key_idx] * (1 - matched); - } - hasMatched[idx] = IsEqual(); - hasMatched[idx].in <== [stringMatch[idx].out, 1]; - matched += hasMatched[idx].out; - counter += (1 - matched); // TODO: Off by one? Move before? - } - position <== counter; -} - -component main { public [step_in] } = LockHeader(4160, 320, 12, 31); +component main { public [step_in] } = LockHeader(48, 16, 12, 16); +// this one took about diff --git a/circuits/http_parse_and_lock_start_line.circom b/circuits/http_parse_and_lock_start_line.circom index d47d50b..f0ba8a5 100644 --- a/circuits/http_parse_and_lock_start_line.circom +++ b/circuits/http_parse_and_lock_start_line.circom @@ -1,126 +1,5 @@ pragma circom 2.1.9; -include "parser-attestor/circuits/http/parser/machine.circom"; -include "parser-attestor/circuits/http/interpreter.circom"; -include "parser-attestor/circuits/utils/bytes.circom"; +include "http/nivc/parse_and_lock_start_line.circom"; -// TODO: Note that TOTAL_BYTES will match what we have for AESGCMFOLD step_out -// I have not gone through to double check the sizes of everything yet. -template LockStartLine(TOTAL_BYTES, DATA_BYTES, beginningLen, middleLen, finalLen) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ Set sizes at compile time ~~ - // Total number of variables in the parser for each byte of data - var AES_BYTES = DATA_BYTES + 50; // TODO: Might be wrong, but good enough for now - var PER_ITERATION_DATA_LENGTH = 5; - var TOTAL_BYTES_USED = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); // data + parser vars - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (JsonParseNIVC) - signal input step_in[TOTAL_BYTES]; - - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[50 + i]; - } - - // // TODO: check if these needs to here or not - // component dataASCII = ASCII(DATA_BYTES); - // dataASCII.in <== data; - - signal input beginning[beginningLen]; - signal input middle[middleLen]; - signal input final[finalLen]; - - // Initialze the parser - component State[DATA_BYTES]; - State[0] = HttpStateUpdate(); - State[0].byte <== data[0]; - State[0].parsing_start <== 1; - State[0].parsing_header <== 0; - State[0].parsing_field_name <== 0; - State[0].parsing_field_value <== 0; - State[0].parsing_body <== 0; - State[0].line_status <== 0; - - /* - Note, because we know a beginning is the very first thing in a request - we can make this more efficient by just comparing the first `beginningLen` bytes - of the data ASCII against the beginning ASCII itself. - */ - // Check first beginning byte - signal beginningIsEqual[beginningLen]; - beginningIsEqual[0] <== IsEqual()([data[0],beginning[0]]); - beginningIsEqual[0] === 1; - - // Setup to check middle bytes - signal startLineMask[DATA_BYTES]; - signal middleMask[DATA_BYTES]; - signal finalMask[DATA_BYTES]; - - var middle_start_counter = 1; - var middle_end_counter = 1; - var final_end_counter = 1; - for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) { - State[data_idx] = HttpStateUpdate(); - State[data_idx].byte <== data[data_idx]; - State[data_idx].parsing_start <== State[data_idx - 1].next_parsing_start; - State[data_idx].parsing_header <== State[data_idx - 1].next_parsing_header; - State[data_idx].parsing_field_name <== State[data_idx - 1].next_parsing_field_name; - State[data_idx].parsing_field_value <== State[data_idx - 1].next_parsing_field_value; - State[data_idx].parsing_body <== State[data_idx - 1].next_parsing_body; - State[data_idx].line_status <== State[data_idx - 1].next_line_status; - - // Check remaining beginning bytes - if(data_idx < beginningLen) { - beginningIsEqual[data_idx] <== IsEqual()([data[data_idx], beginning[data_idx]]); - beginningIsEqual[data_idx] === 1; - } - - // Set the masks based on parser state - startLineMask[data_idx] <== inStartLine()(State[data_idx].parsing_start); - middleMask[data_idx] <== inStartMiddle()(State[data_idx].parsing_start); - finalMask[data_idx] <== inStartEnd()(State[data_idx].parsing_start); - - // Increment counters based on mask information - middle_start_counter += startLineMask[data_idx] - middleMask[data_idx] - finalMask[data_idx]; - middle_end_counter += startLineMask[data_idx] - finalMask[data_idx]; - final_end_counter += startLineMask[data_idx]; - } - - // Additionally verify beginning had correct length - beginningLen === middle_start_counter - 1; - - // Check middle is correct by substring match and length check - signal middleMatch <== SubstringMatchWithIndex(DATA_BYTES, middleLen)(data, middle, middle_start_counter); - middleMatch === 1; - middleLen === middle_end_counter - middle_start_counter - 1; - - // Check final is correct by substring match and length check - signal finalMatch <== SubstringMatchWithIndex(DATA_BYTES, finalLen)(data, final, middle_end_counter); - finalMatch === 1; - // -2 here for the CRLF - finalLen === final_end_counter - middle_end_counter - 2; - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Write out to next NIVC step (Lock Header) - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - // add plaintext http input to step_out - step_out[i] <== step_in[50 + i]; - - // add parser state - step_out[DATA_BYTES + i * 5] <== State[i].next_parsing_start; - step_out[DATA_BYTES + i * 5 + 1] <== State[i].next_parsing_header; - step_out[DATA_BYTES + i * 5 + 2] <== State[i].next_parsing_field_name; - step_out[DATA_BYTES + i * 5 + 3] <== State[i].next_parsing_field_value; - step_out[DATA_BYTES + i * 5 + 4] <== State[i].next_parsing_body; - } - // Pad remaining with zeros - for (var i = TOTAL_BYTES_USED ; i < TOTAL_BYTES ; i++ ) { - step_out[i] <== 0; - } -} - -component main { public [step_in] } = LockStartLine(4160, 320, 8, 3, 2); \ No newline at end of file +component main { public [step_in] } = ParseAndLockStartLine(48, 16, 8, 3, 2); \ No newline at end of file diff --git a/circuits/json/nivc/extractor.circom b/circuits/json/nivc/extractor.circom index aadb436..f3d48eb 100644 --- a/circuits/json/nivc/extractor.circom +++ b/circuits/json/nivc/extractor.circom @@ -42,6 +42,4 @@ template MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH) { } // TODO: Do anything with last depth? // step_out[TOTAL_BYTES_ACROSS_NIVC - 1] <== 0; -} - -// component main { public [step_in] } = MaskExtractFinal(4160, 320, 200); \ No newline at end of file +} \ No newline at end of file diff --git a/circuits/json_mask_array_index.circom b/circuits/json_mask_array_index.circom index 5cf36c7..dfe2334 100644 --- a/circuits/json_mask_array_index.circom +++ b/circuits/json_mask_array_index.circom @@ -1,71 +1,5 @@ pragma circom 2.1.9; -include "parser-attestor/circuits/json/interpreter.circom"; +include "json/nivc/masker.circom"; -template JsonMaskArrayIndexNIVC(TOTAL_BYTES, DATA_BYTES, MAX_STACK_HEIGHT) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ 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_USED = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (JsonParseNIVC) - signal input step_in[TOTAL_BYTES]; - - // Grab the raw data bytes from the `step_in` variable - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } - - // Decode the encoded data in `step_in` back into parser variables - signal stack[DATA_BYTES][MAX_STACK_HEIGHT][2]; - signal parsingData[DATA_BYTES][2]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - for (var j = 0 ; j < MAX_STACK_HEIGHT ; j++) { - stack[i][j][0] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2]; - stack[i][j][1] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2 + 1]; - } - parsingData[i][0] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2]; - parsingData[i][1] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2 + 1]; - } - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Array index masking ~ - signal input index; - - // value starting index in `data` - signal value_starting_index[DATA_BYTES]; - signal mask[DATA_BYTES]; - - signal parsing_array[DATA_BYTES]; - signal or[DATA_BYTES]; - - parsing_array[0] <== InsideArrayIndexObject()(stack[0][0], stack[0][1], parsingData[0][0], parsingData[0][1], index); - mask[0] <== data[0] * parsing_array[0]; - - for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) { - parsing_array[data_idx] <== InsideArrayIndexObject()(stack[data_idx][0], stack[data_idx][1], parsingData[data_idx][0], parsingData[data_idx][1], index); - - or[data_idx] <== OR()(parsing_array[data_idx], parsing_array[data_idx - 1]); - mask[data_idx] <== data[data_idx] * or[data_idx]; - } - - // Write the `step_out` with masked data - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - step_out[i] <== mask[i]; - } - // Append the parser state back on `step_out` - for (var i = DATA_BYTES ; i < TOTAL_BYTES ; i++) { - step_out[i] <== step_in[i]; - } - // No need to pad as this is currently when TOTAL_BYTES == TOTAL_BYTES_USED -} - -component main { public [step_in] } = JsonMaskArrayIndexNIVC(4160, 320, 5); \ No newline at end of file +component main { public [step_in] } = JsonMaskArrayIndexNIVC(48, 16); \ No newline at end of file diff --git a/circuits/json_mask_object.circom b/circuits/json_mask_object.circom index 89b7135..5f49944 100644 --- a/circuits/json_mask_object.circom +++ b/circuits/json_mask_object.circom @@ -1,110 +1,5 @@ pragma circom 2.1.9; -include "parser-attestor/circuits/json/interpreter.circom"; +include "json/nivc/masker.circom"; -template JsonMaskObjectNIVC(TOTAL_BYTES, DATA_BYTES, MAX_STACK_HEIGHT, maxKeyLen) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ 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_USED = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); // data + parser vars - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Unravel from previous NIVC step ~ - // Read in from previous NIVC step (JsonParseNIVC) - signal input step_in[TOTAL_BYTES]; - - // Grab the raw data bytes from the `step_in` variable - signal data[DATA_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - data[i] <== step_in[i]; - } - - // Decode the encoded data in `step_in` back into parser variables - signal stack[DATA_BYTES][MAX_STACK_HEIGHT][2]; - signal parsingData[DATA_BYTES][2]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - for (var j = 0 ; j < MAX_STACK_HEIGHT ; j++) { - stack[i][j][0] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2]; - stack[i][j][1] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2 + 1]; - } - parsingData[i][0] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2]; - parsingData[i][1] <== step_in[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2 + 1]; - } - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Object masking ~ - // Key data to use to point to which object to extract - signal input key[maxKeyLen]; - signal input keyLen; - - // flag determining whether this byte is matched value - signal is_value_match[DATA_BYTES - maxKeyLen]; - // final mask - signal mask[DATA_BYTES - maxKeyLen]; - - - // signal parsing_object_value[DATA_BYTES - maxKeyLen]; - signal is_key_match[DATA_BYTES - maxKeyLen]; - signal is_key_match_for_value[DATA_BYTES + 1 - maxKeyLen]; - is_key_match_for_value[0] <== 0; - signal is_next_pair_at_depth[DATA_BYTES - maxKeyLen]; - signal or[DATA_BYTES - maxKeyLen]; - - // Signals to detect if we are parsing a key or value with initial setup - signal parsing_key[DATA_BYTES - maxKeyLen]; - signal parsing_value[DATA_BYTES - maxKeyLen]; - // TODO: Can't these just be 0 since the start of object can't be either of these? - // parsing_key[0] <== InsideKey()(stack[0][0], parsingData[0][0], parsingData[0][1]); - // parsing_value[0] <== InsideValueObject()(stack[0][0], stack[0][1], parsingData[0][0], parsingData[0][1]); - - // Initialize values knowing 0th bit of data will never be a key/value - parsing_key[0] <== 0; - parsing_value[0] <== 0; - is_key_match[0] <== 0; - - is_next_pair_at_depth[0] <== NextKVPairAtDepth(MAX_STACK_HEIGHT, 0)(stack[0], data[0]); - is_key_match_for_value[1] <== Mux1()([is_key_match_for_value[0] * (1-is_next_pair_at_depth[0]), is_key_match[0] * (1-is_next_pair_at_depth[0])], is_key_match[0]); - is_value_match[0] <== parsing_value[0] * is_key_match_for_value[1]; - - mask[0] <== data[0] * is_value_match[0]; - - for(var data_idx = 1; data_idx < DATA_BYTES - maxKeyLen; data_idx++) { - parsing_key[data_idx] <== InsideKey()(stack[data_idx][0], parsingData[data_idx][0], parsingData[data_idx][1]); - parsing_value[data_idx] <== InsideValueObject()(stack[data_idx][0], stack[data_idx][1], parsingData[data_idx][0], parsingData[data_idx][1]); - - // to get correct value, check: - // - key matches at current index and depth of key is as specified - // - whether next KV pair starts - // - whether key matched for a value (propogate key match until new KV pair of lower depth starts) - is_key_match[data_idx] <== KeyMatchAtIndex(DATA_BYTES, maxKeyLen, data_idx)(data, key, keyLen, parsing_key[data_idx]); - is_next_pair_at_depth[data_idx] <== NextKVPairAtDepth(MAX_STACK_HEIGHT, 0)(stack[data_idx], data[data_idx]); - is_key_match_for_value[data_idx+1] <== Mux1()([is_key_match_for_value[data_idx] * (1-is_next_pair_at_depth[data_idx]), is_key_match[data_idx] * (1-is_next_pair_at_depth[data_idx])], is_key_match[data_idx]); - is_value_match[data_idx] <== is_key_match_for_value[data_idx+1] * parsing_value[data_idx]; - - or[data_idx] <== OR()(is_value_match[data_idx], is_value_match[data_idx - 1]); - - // mask = currently parsing value and all subsequent keys matched - mask[data_idx] <== data[data_idx] * or[data_idx]; - - } - - // Write the `step_out` with masked data - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES - maxKeyLen ; i++) { - step_out[i] <== mask[i]; - } - for (var i = 0 ; i < maxKeyLen ; i++) { - step_out[DATA_BYTES - maxKeyLen + i] <== 0; - } - // Append the parser state back on `step_out` - for (var i = DATA_BYTES ; i < TOTAL_BYTES ; i++) { - step_out[i] <== step_in[i]; - } - // No need to pad as this is currently when TOTAL_BYTES == TOTAL_BYTES_USED -} - -component main { public [step_in] } = JsonMaskObjectNIVC(4160, 320, 5, 10); +component main { public [step_in] } = JsonMaskObjectNIVC(48, 16, 5); diff --git a/circuits/json_parse.circom b/circuits/json_parse.circom index db2e154..3204dff 100644 --- a/circuits/json_parse.circom +++ b/circuits/json_parse.circom @@ -1,60 +1,6 @@ pragma circom 2.1.9; -include "parser-attestor/circuits/json/parser/parser.circom"; +include "json/nivc/parse.circom"; -template JsonParseNIVC(TOTAL_BYTES, DATA_BYTES, MAX_STACK_HEIGHT) { - // ------------------------------------------------------------------------------------------------------------------ // - // ~~ Set sizes at compile time ~~ - // Total number of variables in the parser for each byte of data - var PER_ITERATION_DATA_LENGTH = MAX_STACK_HEIGHT * 2 + 2; - var TOTAL_BYTES_USED = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1); - // ------------------------------------------------------------------------------------------------------------------ // - - // Read in from previous NIVC step (AESNIVC) - signal input step_in[TOTAL_BYTES]; - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Parse JSON ~ - // Initialize the parser - component State[DATA_BYTES]; - State[0] = StateUpdate(MAX_STACK_HEIGHT); - for(var i = 0; i < MAX_STACK_HEIGHT; i++) { - State[0].stack[i] <== [0,0]; - } - State[0].parsing_string <== 0; - State[0].parsing_number <== 0; - State[0].byte <== step_in[0]; - - // Parse all the data to generate the complete parser state - for(var i = 1; i < DATA_BYTES; i++) { - State[i] = StateUpdate(MAX_STACK_HEIGHT); - State[i].byte <== step_in[i]; - State[i].stack <== State[i - 1].next_stack; - State[i].parsing_string <== State[i - 1].next_parsing_string; - State[i].parsing_number <== State[i - 1].next_parsing_number; - } - // ------------------------------------------------------------------------------------------------------------------ // - - // ------------------------------------------------------------------------------------------------------------------ // - // ~ Write to `step_out` for next NIVC step - // Pass the data bytes back out in the first `step_out` signals - signal output step_out[TOTAL_BYTES]; - for (var i = 0 ; i < DATA_BYTES ; i++) { - step_out[i] <== step_in[i]; - } - - // Decode the parser state into the `step_out` remaining signals - for (var i = 0 ; i < DATA_BYTES ; i++) { - for (var j = 0 ; j < MAX_STACK_HEIGHT ; j++) { - step_out[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2] <== State[i].next_stack[j][0]; - step_out[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + j * 2 + 1] <== State[i].next_stack[j][1]; - } - step_out[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2] <== State[i].next_parsing_string; - step_out[DATA_BYTES + i * PER_ITERATION_DATA_LENGTH + MAX_STACK_HEIGHT * 2 + 1] <== State[i].next_parsing_number; - } - // No need to pad as this is currently when TOTAL_BYTES == TOTAL_BYTES_USED - // ------------------------------------------------------------------------------------------------------------------ // -} - -component main { public [step_in] } = JsonParseNIVC(4160, 320, 5); +component main { public [step_in] } = JsonParseNIVC(48, 16); diff --git a/package-lock.json b/package-lock.json index acf451a..b4e8631 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,16 @@ { "name": "web-prover-circuits", - "version": "0.2.4", + "version": "0.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "web-prover-circuits", - "version": "0.2.4", + "version": "0.2.5", "license": "Apache-2.0", "dependencies": { "@zk-email/circuits": "^6.1.1", - "aes-proof": "github:pluto/aes-proof#1d08e13ea4f381649cdff83f56d93444008b6548", - "circomlib": "^2.0.5", - "parser-attestor": "github:pluto/parser-attestor#b9feeeb240ddf867da85198de7d59e73cba4b008" + "circomlib": "^2.0.5" }, "devDependencies": { "@semantic-release/commit-analyzer": "^11.1.0", @@ -91,6 +89,7 @@ "version": "0.0.11", "resolved": "https://registry.npmjs.org/@iden3/binfileutils/-/binfileutils-0.0.11.tgz", "integrity": "sha512-LylnJoZ0CTdgErnKY8OxohvW4K+p6UHD3sxt+3P9AmMyBQjYR4IpoqoYZZ+9aMj89cmCQ21UvdhndAx04er3NA==", + "dev": true, "license": "GPL-3.0", "dependencies": { "fastfile": "0.0.20", @@ -917,6 +916,7 @@ "version": "0.7.8", "resolved": "https://registry.npmjs.org/@types/snarkjs/-/snarkjs-0.7.8.tgz", "integrity": "sha512-x37Jsv1vx6I6RMJdfvYEmDUOLYgzYMecwlk13gniDOcN20xLVe9hy9DlQxWeCPirqpDY/jwugQSqCi2RxehU3g==", + "dev": true, "license": "MIT", "peer": true }, @@ -976,37 +976,6 @@ "node": ">=0.4.0" } }, - "node_modules/aes-proof": { - "version": "0.1.0", - "resolved": "git+ssh://git@github.com/pluto/aes-proof.git#1d08e13ea4f381649cdff83f56d93444008b6548", - "integrity": "sha512-e/wiJJgISYDBE47vddzI3nyM1odtYqvH55AOYHQQWu5otp7KUuwHI+oO6XVsbQuPr992jo1+CQbqs19Jb1I+UQ==", - "license": "Apache-2.0", - "dependencies": { - "circomkit": "^0.2.1", - "circomlib": "^2.0.5" - } - }, - "node_modules/aes-proof/node_modules/circomkit": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/circomkit/-/circomkit-0.2.1.tgz", - "integrity": "sha512-7O8QsOLUq2QvwGMimvWxwdg7OgV33OT7ZBND+81dv3JrVp8ove93yV16jF3TW6XBncSY92/Aka8F4CAi/H9VQw==", - "license": "MIT", - "dependencies": { - "circom_tester": "^0.0.19", - "commander": "^12.0.0", - "loglevel": "^1.8.1" - }, - "bin": { - "circomkit": "dist/cli.js" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/snarkjs": "^0.7.x", - "snarkjs": "^0.7.x" - } - }, "node_modules/agent-base": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", @@ -1138,6 +1107,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, "license": "MIT", "engines": { "node": "*" @@ -1153,6 +1123,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "license": "MIT", "dependencies": { "possible-typed-array-names": "^1.0.0" @@ -1269,6 +1240,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -1311,6 +1283,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", @@ -1355,6 +1328,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" @@ -1373,6 +1347,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==", + "dev": true, "license": "ISC" }, "node_modules/chokidar": { @@ -1427,6 +1402,7 @@ "version": "0.0.19", "resolved": "https://registry.npmjs.org/circom_tester/-/circom_tester-0.0.19.tgz", "integrity": "sha512-SNHaBsGxcBH6XsVWfsRbRPA7NF8m8AMKJI9dtJJCFGUtOTT2+zsoIqAwi50z6XCnO4TtjyXq7AeXa1PLHqT0tw==", + "dev": true, "license": "GPL-3.0", "dependencies": { "chai": "^4.3.6", @@ -1443,6 +1419,7 @@ "version": "0.1.21", "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.21.tgz", "integrity": "sha512-qTkud630B/GK8y76hnOaaS1aNuF6prfV0dTrkeRsiJKnlP1ryQbP2FWLgDOPqn6aKyaPlam+Z+DTbBhkEzh8dA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "ffjavascript": "0.2.56" @@ -1455,6 +1432,7 @@ "version": "0.2.56", "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.56.tgz", "integrity": "sha512-em6G5Lrj7ucIqj4TYEgyoHs/j99Urwwqa4+YxEVY2hggnpRimVj+noX5pZQTxI1pvtiekZI4rG65JBf0xraXrg==", + "dev": true, "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16", @@ -1466,6 +1444,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.5.0.tgz", "integrity": "sha512-KWz8mZ2Y+6wvn6GGkQo6/ZlKwETdAGohd40Lzpwp5TUZCn6N6O4Az1SuX1rw/qREGL6Im+ycb19suCFE8/xaKA==", + "dev": true, "license": "GPL-3.0", "dependencies": { "@iden3/binfileutils": "0.0.11", @@ -1487,6 +1466,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.0.tgz", "integrity": "sha512-3e2rbxdujOwaod657gxgmdhZNn+i1qKdHO3Y/bK+8E7bV8ttV/fu5FO4/WLBACF375cK0QDLOP+65Na63qYuWA==", + "dev": true, "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16" @@ -1646,6 +1626,7 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -1894,6 +1875,7 @@ "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, "license": "MIT", "dependencies": { "type-detect": "^4.0.0" @@ -1922,6 +1904,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -2212,6 +2195,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, "license": "MIT", "dependencies": { "get-intrinsic": "^1.2.4" @@ -2224,6 +2208,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2397,6 +2382,7 @@ "version": "0.2.63", "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", "integrity": "sha512-dBgdsfGks58b66JnUZeZpGxdMIDQ4QsD3VYlRJyFVrKQHb2kJy4R2gufx5oetrTxXPT+aEjg0dOvOLg1N0on4A==", + "dev": true, "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16", @@ -2520,12 +2506,14 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/fnv-plus/-/fnv-plus-1.3.1.tgz", "integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw==", + "dev": true, "license": "MIT" }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, "license": "MIT", "dependencies": { "is-callable": "^1.1.3" @@ -2583,6 +2571,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2615,6 +2604,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, "license": "MIT", "engines": { "node": "*" @@ -2624,6 +2614,7 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -2772,6 +2763,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" @@ -2822,6 +2814,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -2834,6 +2827,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2846,6 +2840,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2858,6 +2853,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -2873,6 +2869,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3075,6 +3072,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -3105,6 +3103,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.2", @@ -3141,6 +3140,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -3173,6 +3173,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" @@ -3260,6 +3261,7 @@ "version": "1.1.13", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, "license": "MIT", "dependencies": { "which-typed-array": "^1.1.14" @@ -3588,6 +3590,7 @@ "version": "1.9.2", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6.0" @@ -3607,6 +3610,7 @@ "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" @@ -7442,16 +7446,6 @@ "dev": true, "license": "MIT" }, - "node_modules/parser-attestor": { - "version": "0.1.0", - "resolved": "git+ssh://git@github.com/pluto/parser-attestor.git#b9feeeb240ddf867da85198de7d59e73cba4b008", - "integrity": "sha512-8yldptobgJKXHzSpb1/xdtEQLHqzGb55bqrdyTbapyZ1zR482FKiS4RXw8gXKwKGLQK0WNSumYDbh8BBqlJGgw==", - "license": "Apache-2.0", - "dependencies": { - "@zk-email/circuits": "^6.1.1", - "circomlib": "^2.0.5" - } - }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -7486,6 +7480,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, "license": "MIT", "engines": { "node": "*" @@ -7546,6 +7541,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7614,6 +7610,7 @@ "version": "0.0.41", "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.41.tgz", "integrity": "sha512-Q1WDF3u1vYeAwjHo4YuddkA8Aq0TulbKjmGm99+Atn13Lf5fTsMZBnBV9T741w8iSyPFG6Uh6sapQby77sREqA==", + "dev": true, "license": "GPL-3.0", "dependencies": { "@iden3/bigarray": "0.0.2", @@ -7626,6 +7623,7 @@ "version": "0.2.56", "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.56.tgz", "integrity": "sha512-em6G5Lrj7ucIqj4TYEgyoHs/j99Urwwqa4+YxEVY2hggnpRimVj+noX5pZQTxI1pvtiekZI4rG65JBf0xraXrg==", + "dev": true, "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16", @@ -7637,6 +7635,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.2.0.tgz", "integrity": "sha512-3e2rbxdujOwaod657gxgmdhZNn+i1qKdHO3Y/bK+8E7bV8ttV/fu5FO4/WLBACF375cK0QDLOP+65Na63qYuWA==", + "dev": true, "license": "GPL-3.0", "dependencies": { "wasmbuilder": "0.0.16" @@ -8448,6 +8447,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -9003,6 +9003,7 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, "license": "MIT", "engines": { "node": ">=14.14" @@ -9012,6 +9013,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, "license": "MIT", "dependencies": { "tmp": "^0.2.0" @@ -9119,6 +9121,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -9248,6 +9251,7 @@ "version": "0.12.5", "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -9323,6 +9327,7 @@ "version": "1.1.15", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", diff --git a/package.json b/package.json index d2e637d..4f472fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "web-prover-circuits", "description": "ZK Circuits for WebProofs", - "version": "0.2.4", + "version": "0.2.5", "license": "Apache-2.0", "repository": { "type": "git", @@ -13,9 +13,7 @@ }, "dependencies": { "@zk-email/circuits": "^6.1.1", - "aes-proof": "github:pluto/aes-proof#1d08e13ea4f381649cdff83f56d93444008b6548", - "circomlib": "^2.0.5", - "parser-attestor": "github:pluto/parser-attestor#b9feeeb240ddf867da85198de7d59e73cba4b008" + "circomlib": "^2.0.5" }, "devDependencies": { "@semantic-release/commit-analyzer": "^11.1.0", From 69c6129472e2b5af118c0685dad636d5814c6a54 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 11:38:07 +0700 Subject: [PATCH 03/21] compose web_proof.circom --- circuits/aes-gctr-nivc.circom | 6 ---- circuits/extract_value.circom | 5 ---- circuits/http_body_mask.circom | 6 ---- circuits/http_lock_header.circom | 7 ----- .../http_parse_and_lock_start_line.circom | 5 ---- circuits/json_mask_array_index.circom | 5 ---- circuits/json_mask_object.circom | 5 ---- circuits/json_parse.circom | 6 ---- circuits/web_proof.circom | 30 +++++++++++++++++++ 9 files changed, 30 insertions(+), 45 deletions(-) delete mode 100644 circuits/aes-gctr-nivc.circom delete mode 100644 circuits/extract_value.circom delete mode 100644 circuits/http_body_mask.circom delete mode 100644 circuits/http_lock_header.circom delete mode 100644 circuits/http_parse_and_lock_start_line.circom delete mode 100644 circuits/json_mask_array_index.circom delete mode 100644 circuits/json_mask_object.circom delete mode 100644 circuits/json_parse.circom create mode 100644 circuits/web_proof.circom diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom deleted file mode 100644 index 2ec7580..0000000 --- a/circuits/aes-gctr-nivc.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "aes-gcm/nivc/aes-gctr-nivc.circom"; - -// the circomkit tests become unhappy when there is a main. -component main { public [step_in] } = AESGCTRFOLD(48); \ No newline at end of file diff --git a/circuits/extract_value.circom b/circuits/extract_value.circom deleted file mode 100644 index 8e3906b..0000000 --- a/circuits/extract_value.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/extractor.circom"; - -component main { public [step_in] } = MaskExtractFinal(49, 32, 32); \ No newline at end of file diff --git a/circuits/http_body_mask.circom b/circuits/http_body_mask.circom deleted file mode 100644 index de2a95c..0000000 --- a/circuits/http_body_mask.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/body_mask.circom"; - -component main { public [step_in] } = HTTPMaskBodyNIVC(4160, 320); - diff --git a/circuits/http_lock_header.circom b/circuits/http_lock_header.circom deleted file mode 100644 index c81aa82..0000000 --- a/circuits/http_lock_header.circom +++ /dev/null @@ -1,7 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/lock_header.circom"; - -component main { public [step_in] } = LockHeader(48, 16, 12, 16); -// this one took about - diff --git a/circuits/http_parse_and_lock_start_line.circom b/circuits/http_parse_and_lock_start_line.circom deleted file mode 100644 index f0ba8a5..0000000 --- a/circuits/http_parse_and_lock_start_line.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/parse_and_lock_start_line.circom"; - -component main { public [step_in] } = ParseAndLockStartLine(48, 16, 8, 3, 2); \ No newline at end of file diff --git a/circuits/json_mask_array_index.circom b/circuits/json_mask_array_index.circom deleted file mode 100644 index dfe2334..0000000 --- a/circuits/json_mask_array_index.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/masker.circom"; - -component main { public [step_in] } = JsonMaskArrayIndexNIVC(48, 16); \ No newline at end of file diff --git a/circuits/json_mask_object.circom b/circuits/json_mask_object.circom deleted file mode 100644 index 5f49944..0000000 --- a/circuits/json_mask_object.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/masker.circom"; - -component main { public [step_in] } = JsonMaskObjectNIVC(48, 16, 5); diff --git a/circuits/json_parse.circom b/circuits/json_parse.circom deleted file mode 100644 index 3204dff..0000000 --- a/circuits/json_parse.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/parse.circom"; - -component main { public [step_in] } = JsonParseNIVC(48, 16); - diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom new file mode 100644 index 0000000..177486b --- /dev/null +++ b/circuits/web_proof.circom @@ -0,0 +1,30 @@ +pragma circom 2.1.9; + +include "aes-gcm/nivc/aes-gctr-nivc.circom"; +include "http/nivc/parse_and_lock_start_line.circom"; +include "http/nivc/lock_header.circom"; +include "http/nivc/body_mask.circom"; +include "json/nivc/parse.circom"; +include "json/nivc/masker.circom"; +include "json/nivc/masker.circom"; +include "json/nivc/extractor.circom"; + +// AES -> HTTP Parse -> http lock header -> http body mask -> json parse -> json_mask_object/json_mask_array -> extract value +template WEPPROOF { + + component aes_gctr_nivc = AESGCTRFOLD(48); + component http_parse = ParseAndLockStartLine(48, 16, 8, 3, 2); + component http_lock_header = LockHeader(48, 16, 12, 16); + component http_body_mask = HTTPMaskBodyNIVC(48, 16); + component json_parse = JsonParseNIVC(48, 16); + // need logic to specif which json type + // object or array + component json_mask_object = JsonMaskObjectNIVC(48, 16, 4); + component json_mask_array = JsonMaskArrayIndexNIVC(48, 16); + // extract value + component extract_value = JsonParseNIVC(48, 16); +} + +// = AESGCTRFOLD(48); +component main = WEPPROOF(); + From 784db469888a9b66daec8e3600db7c28d0b72e09 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 11:43:49 +0700 Subject: [PATCH 04/21] compose web_proof.circom --- circuits/web_proof.circom | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom index 177486b..ecd2c5c 100644 --- a/circuits/web_proof.circom +++ b/circuits/web_proof.circom @@ -12,17 +12,28 @@ include "json/nivc/extractor.circom"; // AES -> HTTP Parse -> http lock header -> http body mask -> json parse -> json_mask_object/json_mask_array -> extract value template WEPPROOF { + // template AESGCTRFOLD(INPUT_LEN) component aes_gctr_nivc = AESGCTRFOLD(48); + + // template ParseAndLockStartLine(DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) component http_parse = ParseAndLockStartLine(48, 16, 8, 3, 2); + + // template LockHeader(DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) component http_lock_header = LockHeader(48, 16, 12, 16); + + // template HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT) component http_body_mask = HTTPMaskBodyNIVC(48, 16); + + // JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT) component json_parse = JsonParseNIVC(48, 16); // need logic to specif which json type // object or array + + component json_mask_object = JsonMaskObjectNIVC(48, 16, 4); component json_mask_array = JsonMaskArrayIndexNIVC(48, 16); // extract value - component extract_value = JsonParseNIVC(48, 16); + component extract_value = MaskExtractFinal(49, 32, 32); } // = AESGCTRFOLD(48); From 118d4cb2d12bfb7cc0b30b60dfad9f78c71d8fb7 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 11:55:33 +0700 Subject: [PATCH 05/21] change aes input to data bytes --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 6 ++-- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 8 ++--- circuits/web_proof.circom | 30 +++++++++++-------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 689da97..995fe9e 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -5,9 +5,11 @@ include "../../utils/array.circom"; // Compute AES-GCTR -template AESGCTRFOLD(INPUT_LEN) { +template AESGCTRFOLD(DATA_BYTES) { + // Length of plaintext + var INPUT_LEN = (DATA_BYTES - 4) / 2; assert(INPUT_LEN % 16 == 0); - var DATA_BYTES = (INPUT_LEN * 2) + 4; + signal input key[16]; signal input iv[12]; signal input aad[16]; diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index 4b63918..75de5dd 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -9,7 +9,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [16], // input len is 16 bytes + params: [36], // input len is 16 bytes }); let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -30,7 +30,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [16], // input len is 16 bytes + params: [36], // input len is 16 bytes }); let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; @@ -54,7 +54,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [68], // input len is 32 bytes }); let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -78,7 +78,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [68], // input len is 32 bytes }); let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom index ecd2c5c..19ccaf9 100644 --- a/circuits/web_proof.circom +++ b/circuits/web_proof.circom @@ -10,32 +10,36 @@ include "json/nivc/masker.circom"; include "json/nivc/extractor.circom"; // AES -> HTTP Parse -> http lock header -> http body mask -> json parse -> json_mask_object/json_mask_array -> extract value -template WEPPROOF { +// DATA_BYTES = length of block * 2 + 4 +// e.g. 36 = 16 * 2 + 4 for a single block +template WEPPROOF(DATA_BYTES) { - // template AESGCTRFOLD(INPUT_LEN) - component aes_gctr_nivc = AESGCTRFOLD(48); + // template AESGCTRFOLD(DATA) + component aes_gctr_nivc = AESGCTRFOLD(DATA_BYTES); // template ParseAndLockStartLine(DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) - component http_parse = ParseAndLockStartLine(48, 16, 8, 3, 2); + component http_parse = ParseAndLockStartLine(DATA_BYTES, 16, 8, 3, 2); // template LockHeader(DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) - component http_lock_header = LockHeader(48, 16, 12, 16); + component http_lock_header = LockHeader(DATA_BYTES, 16, 12, 16); // template HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT) - component http_body_mask = HTTPMaskBodyNIVC(48, 16); + component http_body_mask = HTTPMaskBodyNIVC(DATA_BYTES, 16); // JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT) - component json_parse = JsonParseNIVC(48, 16); + component json_parse = JsonParseNIVC(DATA_BYTES, 16); // need logic to specif which json type // object or array + // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) + component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, 16, 4); - component json_mask_object = JsonMaskObjectNIVC(48, 16, 4); - component json_mask_array = JsonMaskArrayIndexNIVC(48, 16); - // extract value - component extract_value = MaskExtractFinal(49, 32, 32); + // template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) + component json_mask_array = JsonMaskArrayIndexNIVC(DATA_BYTES, 16); + + // template MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH) + component extract_value = MaskExtractFinal(DATA_BYTES, 32, 32); } -// = AESGCTRFOLD(48); -component main = WEPPROOF(); +component main = WEPPROOF(36); From a67abaefa6121afffd2b95ffd10808ba9ab2ff3c Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 13:59:11 +0700 Subject: [PATCH 06/21] save --- circuits/web_proof.circom | 41 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom index 19ccaf9..7b37db9 100644 --- a/circuits/web_proof.circom +++ b/circuits/web_proof.circom @@ -14,11 +14,46 @@ include "json/nivc/extractor.circom"; // e.g. 36 = 16 * 2 + 4 for a single block template WEPPROOF(DATA_BYTES) { - // template AESGCTRFOLD(DATA) + // AES inputs + signal input key[16]; + signal input iv[12]; + signal input aad[16]; + signal input plainText[16]; + // step_in[0..INPUT_LEN] => accumulate plaintext blocks + // step_in[INPUT_LEN..INPUT_LEN*2] => accumulate ciphertext blocks + // step_in[INPUT_LEN*2..INPUT_LEN*2+4] => accumulate counter + signal input step_in[DATA_BYTES]; + signal output step_out[DATA_BYTES]; + component aes_gctr_nivc = AESGCTRFOLD(DATA_BYTES); + aes_gctr_nivc.key <== key; + aes_gctr_nivc.iv <== iv; + aes_gctr_nivc.aad <== aad; + aes_gctr_nivc.plainText <== plainText; + aes_gctr_nivc.step_in <== step_in; + + // Parse and lock start line inputs + signal input beginning; + signal input beginning_length; + signal input middle; + signal input middle_length; + signal input final; + signal input final_length; + + // ParseAndLockStartLine(DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) + component http_parse = ParseAndLockStartLine(DATA_BYTES, 16, 10, 3, 2); + + http_parse.step_in <== aes_gctr_nivc.step_out; + + // First three bytes are "GET", then zero's for third parameter - 3 bytes + // in this case 4 so we add one zero byte + http_parse.beginning <== [0x47, 0x45, 0x54, 0x00]; + http_parse.beginning_length <== MAX_BEGINNING_LENGTH; + http_parse.middle[MAX_MIDDLE_LENGTH]; + http_parse.middle_length; + http_parse.final[MAX_FINAL_LENGTH]; + http_parse.final_length; - // template ParseAndLockStartLine(DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) - component http_parse = ParseAndLockStartLine(DATA_BYTES, 16, 8, 3, 2); // template LockHeader(DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) component http_lock_header = LockHeader(DATA_BYTES, 16, 12, 16); From 17231845ea7ae67b2f9b6b9de8f481d878767e9d Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 14:08:53 +0700 Subject: [PATCH 07/21] save --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 38 +++++++++--------- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 8 ++-- circuits/web_proof.circom | 39 ++++++++++++------- 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 995fe9e..9a0892a 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -6,26 +6,26 @@ include "../../utils/array.circom"; // Compute AES-GCTR template AESGCTRFOLD(DATA_BYTES) { - // Length of plaintext - var INPUT_LEN = (DATA_BYTES - 4) / 2; - assert(INPUT_LEN % 16 == 0); - + + assert(DATA_BYTES % 16 == 0); + var TOTAL_BYTES_ACROSS_NIVC = (DATA_BYTES * 2) + 4; + signal input key[16]; signal input iv[12]; signal input aad[16]; signal input plainText[16]; - // step_in[0..INPUT_LEN] => accumulate plaintext blocks - // step_in[INPUT_LEN..INPUT_LEN*2] => accumulate ciphertext blocks - // step_in[INPUT_LEN*2..INPUT_LEN*2+4] => accumulate counter - signal input step_in[DATA_BYTES]; - signal output step_out[DATA_BYTES]; + // step_in[0..DATA_BYTES] => accumulate plaintext blocks + // step_in[DATA_BYTES..DATA_BYTES*2] => accumulate ciphertext blocks + // step_in[DATA_BYTES_LEN*2..DATA_BYTES*2+4] => accumulate counter + signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; + signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; signal counter; // We extract the number from the 4 byte word counter component last_counter_bits = BytesToBits(4); for(var i = 0; i < 4; i ++) { - last_counter_bits.in[i] <== step_in[INPUT_LEN*2 + i]; + last_counter_bits.in[i] <== step_in[DATA_BYTES*2 + i]; } component last_counter_num = Bits2Num(32); // pass in reverse order @@ -36,8 +36,8 @@ template AESGCTRFOLD(DATA_BYTES) { counter <== last_counter_num.out - 1; // write new plain text block. - signal plainTextAccumulator[DATA_BYTES]; - component writeToIndex = WriteToIndex(DATA_BYTES, 16); + signal plainTextAccumulator[TOTAL_BYTES_ACROSS_NIVC]; + component writeToIndex = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 16); writeToIndex.array_to_write_to <== step_in; writeToIndex.array_to_write_at_index <== plainText; writeToIndex.index <== counter * 16; @@ -51,22 +51,22 @@ template AESGCTRFOLD(DATA_BYTES) { aes.plainText <== plainText; for(var i = 0; i < 4; i++) { - aes.lastCounter[i] <== step_in[INPUT_LEN*2 + i]; + aes.lastCounter[i] <== step_in[DATA_BYTES*2 + i]; } // accumulate cipher text - signal cipherTextAccumulator[DATA_BYTES]; - component writeCipherText = WriteToIndex(DATA_BYTES, 16); + signal cipherTextAccumulator[TOTAL_BYTES_ACROSS_NIVC]; + component writeCipherText = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 16); writeCipherText.array_to_write_to <== plainTextAccumulator; writeCipherText.array_to_write_at_index <== aes.cipherText; - writeCipherText.index <== INPUT_LEN + counter * 16; + writeCipherText.index <== DATA_BYTES + counter * 16; writeCipherText.out ==> cipherTextAccumulator; // get counter - signal counterAccumulator[DATA_BYTES]; - component writeCounter = WriteToIndex(DATA_BYTES, 4); + signal counterAccumulator[TOTAL_BYTES_ACROSS_NIVC]; + component writeCounter = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 4); writeCounter.array_to_write_to <== cipherTextAccumulator; writeCounter.array_to_write_at_index <== aes.counter; - writeCounter.index <== INPUT_LEN*2; + writeCounter.index <== DATA_BYTES*2; writeCounter.out ==> step_out; } \ No newline at end of file diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index 75de5dd..4b63918 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -9,7 +9,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [36], // input len is 16 bytes + params: [16], // input len is 16 bytes }); let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -30,7 +30,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [36], // input len is 16 bytes + params: [16], // input len is 16 bytes }); let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; @@ -54,7 +54,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [68], // input len is 32 bytes + params: [32], // input len is 32 bytes }); let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; @@ -78,7 +78,7 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [68], // input len is 32 bytes + params: [32], // input len is 32 bytes }); let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom index 7b37db9..a637c71 100644 --- a/circuits/web_proof.circom +++ b/circuits/web_proof.circom @@ -44,33 +44,44 @@ template WEPPROOF(DATA_BYTES) { component http_parse = ParseAndLockStartLine(DATA_BYTES, 16, 10, 3, 2); http_parse.step_in <== aes_gctr_nivc.step_out; - - // First three bytes are "GET", then zero's for third parameter - 3 bytes - // in this case 4 so we add one zero byte - http_parse.beginning <== [0x47, 0x45, 0x54, 0x00]; - http_parse.beginning_length <== MAX_BEGINNING_LENGTH; - http_parse.middle[MAX_MIDDLE_LENGTH]; - http_parse.middle_length; - http_parse.final[MAX_FINAL_LENGTH]; - http_parse.final_length; - + http_parse.beginning <== beginning; + http_parse.beginning_length <== beginning_length; + http_parse.middle <== middle; + http_parse.middle_length <== middle_length; + http_parse.final <== final; + http_parse.final_length <== final_length; // template LockHeader(DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) component http_lock_header = LockHeader(DATA_BYTES, 16, 12, 16); + + signal input header; + signal input headerNameLength; + signal input value; + signal input headerValueLength; + + http_lock_header.step_in <== http_parse.step_out; + http_lock_header.header <== header; + http_lock_header.headerNameLength <== headerNameLength; + http_lock_header.value <== value; + http_lock_header.headerValueLength <== headerValueLength; + // template HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT) component http_body_mask = HTTPMaskBodyNIVC(DATA_BYTES, 16); + http_body_mask.step_in <== http_lock_header.step_out; + // JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT) component json_parse = JsonParseNIVC(DATA_BYTES, 16); - // need logic to specif which json type - // object or array - // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) - component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, 16, 4); + json_parse.step_in <== http_body_mask.step_out; + + // // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) + // component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, 16, 4); // template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) component json_mask_array = JsonMaskArrayIndexNIVC(DATA_BYTES, 16); + json_mask_array.step_in <== json_parse.step_out; // template MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH) component extract_value = MaskExtractFinal(DATA_BYTES, 32, 32); From 493eef52c2b7e29dbc04abb11ec495bf2ef811f9 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 15:18:22 +0700 Subject: [PATCH 08/21] Update web_proof.circom --- circuits/web_proof.circom | 100 +++++++++++++++++++++++++------------- 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom index a637c71..ec2ca1b 100644 --- a/circuits/web_proof.circom +++ b/circuits/web_proof.circom @@ -12,19 +12,26 @@ include "json/nivc/extractor.circom"; // AES -> HTTP Parse -> http lock header -> http body mask -> json parse -> json_mask_object/json_mask_array -> extract value // DATA_BYTES = length of block * 2 + 4 // e.g. 36 = 16 * 2 + 4 for a single block -template WEPPROOF(DATA_BYTES) { - - // AES inputs +template WEPPROOF( + DATA_BYTES, + MAX_STACK_HEIGHT, + MAX_BEGINNING_LENGTH, + MAX_MIDDLE_LENGTH, + MAX_FINAL_LENGTH, + MAX_HEADER_NAME_LENGTH, + MAX_HEADER_VALUE_LENGTH, + MAX_KEY_LENGTH, + MAX_VALUE_LENGTH) { + + var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; + signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; + signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; + + // AES signal input key[16]; signal input iv[12]; signal input aad[16]; signal input plainText[16]; - // step_in[0..INPUT_LEN] => accumulate plaintext blocks - // step_in[INPUT_LEN..INPUT_LEN*2] => accumulate ciphertext blocks - // step_in[INPUT_LEN*2..INPUT_LEN*2+4] => accumulate counter - signal input step_in[DATA_BYTES]; - signal output step_out[DATA_BYTES]; - component aes_gctr_nivc = AESGCTRFOLD(DATA_BYTES); aes_gctr_nivc.key <== key; aes_gctr_nivc.iv <== iv; @@ -32,16 +39,19 @@ template WEPPROOF(DATA_BYTES) { aes_gctr_nivc.plainText <== plainText; aes_gctr_nivc.step_in <== step_in; - // Parse and lock start line inputs - signal input beginning; + // Parse and lock + component http_parse = ParseAndLockStartLine(DATA_BYTES, + MAX_STACK_HEIGHT, + MAX_BEGINNING_LENGTH, + MAX_MIDDLE_LENGTH, + MAX_FINAL_LENGTH); + + signal input beginning[MAX_BEGINNING_LENGTH]; signal input beginning_length; - signal input middle; + signal input middle[MAX_MIDDLE_LENGTH]; signal input middle_length; - signal input final; + signal input final[MAX_FINAL_LENGTH]; signal input final_length; - - // ParseAndLockStartLine(DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) - component http_parse = ParseAndLockStartLine(DATA_BYTES, 16, 10, 3, 2); http_parse.step_in <== aes_gctr_nivc.step_out; http_parse.beginning <== beginning; @@ -51,13 +61,15 @@ template WEPPROOF(DATA_BYTES) { http_parse.final <== final; http_parse.final_length <== final_length; - // template LockHeader(DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) - component http_lock_header = LockHeader(DATA_BYTES, 16, 12, 16); + // Lock header + component http_lock_header = LockHeader(DATA_BYTES, + MAX_STACK_HEIGHT, + MAX_HEADER_NAME_LENGTH, + MAX_HEADER_VALUE_LENGTH); - - signal input header; + signal input header[MAX_HEADER_NAME_LENGTH]; signal input headerNameLength; - signal input value; + signal input value[MAX_HEADER_VALUE_LENGTH]; signal input headerValueLength; http_lock_header.step_in <== http_parse.step_out; @@ -66,26 +78,44 @@ template WEPPROOF(DATA_BYTES) { http_lock_header.value <== value; http_lock_header.headerValueLength <== headerValueLength; - // template HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT) - component http_body_mask = HTTPMaskBodyNIVC(DATA_BYTES, 16); - + // HTTP body mask + component http_body_mask = HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT); http_body_mask.step_in <== http_lock_header.step_out; - // JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT) - component json_parse = JsonParseNIVC(DATA_BYTES, 16); - + // JSON parse + component json_parse = JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT); json_parse.step_in <== http_body_mask.step_out; - // // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) - // component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, 16, 4); + // Note: picked Array over object for now + // TODO(WJ 2024-11-01): add conditional logic via a mux + // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) + // component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH); - // template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) - component json_mask_array = JsonMaskArrayIndexNIVC(DATA_BYTES, 16); + // JSON array + component json_mask_array = JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT); json_mask_array.step_in <== json_parse.step_out; - // template MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH) - component extract_value = MaskExtractFinal(DATA_BYTES, 32, 32); + // Final Extraction + component extract_value = MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH); } - -component main = WEPPROOF(36); +/// Note, DATA_BYTES > MAX_BEGINNING_LENGTH and MAX_MIDDLE_LENGTH and MAX_FINAL_LENGTH +component main = WEPPROOF( + 64, // DATA_BYTES + 5, // MAX_STACK_HEIGHT + 10, // MAX_BEGINNING_LENGTH + 50, // MAX_MIDDLE_LENGTH + 10, // MAX_FINAL_LENGTH + 12, // MAX_HEADER_NAME_LENGTH + 16, // MAX_HEADER_VALUE_LENGTH + 8, // MAX_KEY_LENGTH + 16 // MAX_VALUE_LENGTH + ); + + // const MAX_STACK_HEIGHT = 5; + // const PER_ITERATION_DATA_LENGTH = MAX_STACK_HEIGHT * 2 + 2; + // const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1) + 1; + + // const MAX_BEGINNING_LENGTH = 10; + // const MAX_MIDDLE_LENGTH = 50; + // const MAX_FINAL_LENGTH = 10; \ No newline at end of file From 021b3d7881558d2e496fcceca1209db01fab4515 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 15:35:02 +0700 Subject: [PATCH 09/21] Revert "compose web_proof.circom" This reverts commit 69c6129472e2b5af118c0685dad636d5814c6a54. --- circuits/aes-gctr-nivc.circom | 6 + circuits/extract_value.circom | 5 + circuits/http_body_mask.circom | 6 + circuits/http_lock_header.circom | 7 + .../http_parse_and_lock_start_line.circom | 5 + circuits/json_mask_array_index.circom | 5 + circuits/json_mask_object.circom | 5 + circuits/json_parse.circom | 6 + circuits/web_proof.circom | 121 ------------------ 9 files changed, 45 insertions(+), 121 deletions(-) create mode 100644 circuits/aes-gctr-nivc.circom create mode 100644 circuits/extract_value.circom create mode 100644 circuits/http_body_mask.circom create mode 100644 circuits/http_lock_header.circom create mode 100644 circuits/http_parse_and_lock_start_line.circom create mode 100644 circuits/json_mask_array_index.circom create mode 100644 circuits/json_mask_object.circom create mode 100644 circuits/json_parse.circom delete mode 100644 circuits/web_proof.circom diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom new file mode 100644 index 0000000..2ec7580 --- /dev/null +++ b/circuits/aes-gctr-nivc.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "aes-gcm/nivc/aes-gctr-nivc.circom"; + +// the circomkit tests become unhappy when there is a main. +component main { public [step_in] } = AESGCTRFOLD(48); \ No newline at end of file diff --git a/circuits/extract_value.circom b/circuits/extract_value.circom new file mode 100644 index 0000000..8e3906b --- /dev/null +++ b/circuits/extract_value.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "json/nivc/extractor.circom"; + +component main { public [step_in] } = MaskExtractFinal(49, 32, 32); \ No newline at end of file diff --git a/circuits/http_body_mask.circom b/circuits/http_body_mask.circom new file mode 100644 index 0000000..de2a95c --- /dev/null +++ b/circuits/http_body_mask.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "http/nivc/body_mask.circom"; + +component main { public [step_in] } = HTTPMaskBodyNIVC(4160, 320); + diff --git a/circuits/http_lock_header.circom b/circuits/http_lock_header.circom new file mode 100644 index 0000000..c81aa82 --- /dev/null +++ b/circuits/http_lock_header.circom @@ -0,0 +1,7 @@ +pragma circom 2.1.9; + +include "http/nivc/lock_header.circom"; + +component main { public [step_in] } = LockHeader(48, 16, 12, 16); +// this one took about + diff --git a/circuits/http_parse_and_lock_start_line.circom b/circuits/http_parse_and_lock_start_line.circom new file mode 100644 index 0000000..f0ba8a5 --- /dev/null +++ b/circuits/http_parse_and_lock_start_line.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "http/nivc/parse_and_lock_start_line.circom"; + +component main { public [step_in] } = ParseAndLockStartLine(48, 16, 8, 3, 2); \ No newline at end of file diff --git a/circuits/json_mask_array_index.circom b/circuits/json_mask_array_index.circom new file mode 100644 index 0000000..dfe2334 --- /dev/null +++ b/circuits/json_mask_array_index.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskArrayIndexNIVC(48, 16); \ No newline at end of file diff --git a/circuits/json_mask_object.circom b/circuits/json_mask_object.circom new file mode 100644 index 0000000..5f49944 --- /dev/null +++ b/circuits/json_mask_object.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskObjectNIVC(48, 16, 5); diff --git a/circuits/json_parse.circom b/circuits/json_parse.circom new file mode 100644 index 0000000..3204dff --- /dev/null +++ b/circuits/json_parse.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "json/nivc/parse.circom"; + +component main { public [step_in] } = JsonParseNIVC(48, 16); + diff --git a/circuits/web_proof.circom b/circuits/web_proof.circom deleted file mode 100644 index ec2ca1b..0000000 --- a/circuits/web_proof.circom +++ /dev/null @@ -1,121 +0,0 @@ -pragma circom 2.1.9; - -include "aes-gcm/nivc/aes-gctr-nivc.circom"; -include "http/nivc/parse_and_lock_start_line.circom"; -include "http/nivc/lock_header.circom"; -include "http/nivc/body_mask.circom"; -include "json/nivc/parse.circom"; -include "json/nivc/masker.circom"; -include "json/nivc/masker.circom"; -include "json/nivc/extractor.circom"; - -// AES -> HTTP Parse -> http lock header -> http body mask -> json parse -> json_mask_object/json_mask_array -> extract value -// DATA_BYTES = length of block * 2 + 4 -// e.g. 36 = 16 * 2 + 4 for a single block -template WEPPROOF( - DATA_BYTES, - MAX_STACK_HEIGHT, - MAX_BEGINNING_LENGTH, - MAX_MIDDLE_LENGTH, - MAX_FINAL_LENGTH, - MAX_HEADER_NAME_LENGTH, - MAX_HEADER_VALUE_LENGTH, - MAX_KEY_LENGTH, - MAX_VALUE_LENGTH) { - - var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; - signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; - signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - - // AES - signal input key[16]; - signal input iv[12]; - signal input aad[16]; - signal input plainText[16]; - component aes_gctr_nivc = AESGCTRFOLD(DATA_BYTES); - aes_gctr_nivc.key <== key; - aes_gctr_nivc.iv <== iv; - aes_gctr_nivc.aad <== aad; - aes_gctr_nivc.plainText <== plainText; - aes_gctr_nivc.step_in <== step_in; - - // Parse and lock - component http_parse = ParseAndLockStartLine(DATA_BYTES, - MAX_STACK_HEIGHT, - MAX_BEGINNING_LENGTH, - MAX_MIDDLE_LENGTH, - MAX_FINAL_LENGTH); - - signal input beginning[MAX_BEGINNING_LENGTH]; - signal input beginning_length; - signal input middle[MAX_MIDDLE_LENGTH]; - signal input middle_length; - signal input final[MAX_FINAL_LENGTH]; - signal input final_length; - - http_parse.step_in <== aes_gctr_nivc.step_out; - http_parse.beginning <== beginning; - http_parse.beginning_length <== beginning_length; - http_parse.middle <== middle; - http_parse.middle_length <== middle_length; - http_parse.final <== final; - http_parse.final_length <== final_length; - - // Lock header - component http_lock_header = LockHeader(DATA_BYTES, - MAX_STACK_HEIGHT, - MAX_HEADER_NAME_LENGTH, - MAX_HEADER_VALUE_LENGTH); - - signal input header[MAX_HEADER_NAME_LENGTH]; - signal input headerNameLength; - signal input value[MAX_HEADER_VALUE_LENGTH]; - signal input headerValueLength; - - http_lock_header.step_in <== http_parse.step_out; - http_lock_header.header <== header; - http_lock_header.headerNameLength <== headerNameLength; - http_lock_header.value <== value; - http_lock_header.headerValueLength <== headerValueLength; - - // HTTP body mask - component http_body_mask = HTTPMaskBodyNIVC(DATA_BYTES, MAX_STACK_HEIGHT); - http_body_mask.step_in <== http_lock_header.step_out; - - // JSON parse - component json_parse = JsonParseNIVC(DATA_BYTES, MAX_STACK_HEIGHT); - json_parse.step_in <== http_body_mask.step_out; - - // Note: picked Array over object for now - // TODO(WJ 2024-11-01): add conditional logic via a mux - // template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) - // component json_mask_object = JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH); - - // JSON array - component json_mask_array = JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT); - json_mask_array.step_in <== json_parse.step_out; - - // Final Extraction - component extract_value = MaskExtractFinal(DATA_BYTES, MAX_STACK_HEIGHT, MAX_VALUE_LENGTH); -} - -/// Note, DATA_BYTES > MAX_BEGINNING_LENGTH and MAX_MIDDLE_LENGTH and MAX_FINAL_LENGTH -component main = WEPPROOF( - 64, // DATA_BYTES - 5, // MAX_STACK_HEIGHT - 10, // MAX_BEGINNING_LENGTH - 50, // MAX_MIDDLE_LENGTH - 10, // MAX_FINAL_LENGTH - 12, // MAX_HEADER_NAME_LENGTH - 16, // MAX_HEADER_VALUE_LENGTH - 8, // MAX_KEY_LENGTH - 16 // MAX_VALUE_LENGTH - ); - - // const MAX_STACK_HEIGHT = 5; - // const PER_ITERATION_DATA_LENGTH = MAX_STACK_HEIGHT * 2 + 2; - // const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1) + 1; - - // const MAX_BEGINNING_LENGTH = 10; - // const MAX_MIDDLE_LENGTH = 50; - // const MAX_FINAL_LENGTH = 10; \ No newline at end of file From 6d12a420bdb28068b85b758a522ef208796ab8c2 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 15:45:18 +0700 Subject: [PATCH 10/21] starting on test --- circuits/http_body_mask.circom | 2 +- circuits/http_lock_header.circom | 4 +- circuits/test/full/full.test.ts | 113 +++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 circuits/test/full/full.test.ts diff --git a/circuits/http_body_mask.circom b/circuits/http_body_mask.circom index de2a95c..fedbe20 100644 --- a/circuits/http_body_mask.circom +++ b/circuits/http_body_mask.circom @@ -2,5 +2,5 @@ pragma circom 2.1.9; include "http/nivc/body_mask.circom"; -component main { public [step_in] } = HTTPMaskBodyNIVC(4160, 320); +component main { public [step_in] } = HTTPMaskBodyNIVC(48, 16); diff --git a/circuits/http_lock_header.circom b/circuits/http_lock_header.circom index c81aa82..0bb436e 100644 --- a/circuits/http_lock_header.circom +++ b/circuits/http_lock_header.circom @@ -2,6 +2,4 @@ pragma circom 2.1.9; include "http/nivc/lock_header.circom"; -component main { public [step_in] } = LockHeader(48, 16, 12, 16); -// this one took about - +component main { public [step_in] } = LockHeader(48, 16, 12, 16); \ No newline at end of file diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts new file mode 100644 index 0000000..1b1bbe7 --- /dev/null +++ b/circuits/test/full/full.test.ts @@ -0,0 +1,113 @@ +import { circomkit, WitnessTester, toByte } from "../common"; + +// HTTP/1.1 200 OK +// content-type: application/json; charset=utf-8 +// content-encoding: gzip +// Transfer-Encoding: chunked +// +// { +// "data": { +// "items": [ +// { +// "data": "Artist", +// "profile": { +// "name": "Taylor Swift" +// } +// } +// ] +// } +// } + +// 320 bytes in the HTTP response +let http_response_plaintext = [ + 72, 84, 84, 80, 47, 49, 46, 49, 32, 50, 48, 48, 32, 79, 75, 13, 10, 99, 111, 110, 116, 101, 110, + 116, 45, 116, 121, 112, 101, 58, 32, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 106, + 115, 111, 110, 59, 32, 99, 104, 97, 114, 115, 101, 116, 61, 117, 116, 102, 45, 56, 13, 10, 99, + 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, 105, 110, 103, 58, 32, 103, 122, 105, + 112, 13, 10, 84, 114, 97, 110, 115, 102, 101, 114, 45, 69, 110, 99, 111, 100, 105, 110, 103, 58, + 32, 99, 104, 117, 110, 107, 101, 100, 13, 10, 13, 10, 123, 13, 10, 32, 32, 32, 34, 100, 97, 116, + 97, 34, 58, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, 34, 105, 116, 101, 109, 115, 34, 58, 32, + 91, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 123, 13, 10, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 34, 100, 97, 116, 97, 34, 58, 32, 34, 65, 114, 116, 105, 115, + 116, 34, 44, 13, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 112, 114, + 111, 102, 105, 108, 101, 34, 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, 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, 13, + 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, + 10, 32, 32, 32, 125, 13, 10, 125]; + +describe("NIVC_HTTP", async () => { + let aesCircuit: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; + let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; + let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; + let bodyMaskCircuit: WitnessTester<["step_in"], ["step_out"]>; + + const DATA_BYTES = 320; + const MAX_STACK_HEIGHT = 5; + const PER_ITERATION_DATA_LENGTH = MAX_STACK_HEIGHT * 2 + 2; + const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * (PER_ITERATION_DATA_LENGTH + 1) + 1; + + const MAX_HEADER_NAME_LENGTH = 20; + const MAX_HEADER_VALUE_LENGTH = 35; + const MAX_BEGINNING_LENGTH = 10; + const MAX_MIDDLE_LENGTH = 30; + const MAX_FINAL_LENGTH = 10; + + const beginning = [72, 84, 84, 80, 47, 49, 46, 49]; // HTTP/1.1 + const middle = [50, 48, 48]; // 200 + const final = [79, 75]; // OK + + before(async () => { + aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { + file: "aes-gcm/nivc/aes-gctr-nivc", + template: "AESGCTRFOLD", + params: [DATA_BYTES], + }); + httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { + file: "http/nivc/parse_and_lock_start_line", + template: "ParseAndLockStartLine", + params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], + }); + console.log("#constraints:", await httpParseAndLockStartLineCircuit.getConstraintCount()); + + lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { + file: "http/nivc/lock_header", + template: "LockHeader", + params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], + }); + console.log("#constraints:", await lockHeaderCircuit.getConstraintCount()); + + bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { + file: "http/nivc/body_mask", + template: "HTTPMaskBodyNIVC", + params: [DATA_BYTES, MAX_STACK_HEIGHT], + }); + console.log("#constraints:", await bodyMaskCircuit.getConstraintCount()); + }); + + let extendedJsonInput = http_response_plaintext.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); + + let headerName = toByte("content-type"); + let headerValue = toByte("application/json; charset=utf-8"); + + let headerNamePadded = headerName.concat(Array(MAX_HEADER_NAME_LENGTH - headerName.length).fill(0)); + let headerValuePadded = headerValue.concat(Array(MAX_HEADER_VALUE_LENGTH - headerValue.length).fill(0)); + let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); + let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); + let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); + it("HTTPParseAndExtract", async () => { + let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); + + let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); + + let bodyMask = await bodyMaskCircuit.compute({ step_in: lockHeader.step_out }, ["step_out"]); + + let bodyMaskOut = bodyMask.step_out as number[]; + let idx = bodyMaskOut.indexOf('{'.charCodeAt(0)); + + let maskedInput = extendedJsonInput.fill(0, 0, idx); + maskedInput = maskedInput.fill(0, 320); + + bodyMaskOut === maskedInput; + }); +}); \ No newline at end of file From 757ed4f8978c80c81e7c107754063a77eeb2b349 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Fri, 1 Nov 2024 22:51:28 +0700 Subject: [PATCH 11/21] fix aes fold --- circuits/test/full/full.test.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 1b1bbe7..164dd7a 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -1,3 +1,4 @@ +import { CircuitSignals } from "circomkit"; import { circomkit, WitnessTester, toByte } from "../common"; // HTTP/1.1 200 OK @@ -36,7 +37,7 @@ let http_response_plaintext = [ 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 125, 13, 10, 32, 32, 32, 32, 32, 32, 32, 93, 13, 10, 32, 32, 32, 125, 13, 10, 125]; -describe("NIVC_HTTP", async () => { +describe("NIVC_FULL", async () => { let aesCircuit: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; let httpParseAndLockStartLineCircuit: WitnessTester<["step_in", "beginning", "beginning_length", "middle", "middle_length", "final", "final_length"], ["step_out"]>; let lockHeaderCircuit: WitnessTester<["step_in", "header", "headerNameLength", "value", "headerValueLength"], ["step_out"]>; @@ -85,7 +86,6 @@ describe("NIVC_HTTP", async () => { console.log("#constraints:", await bodyMaskCircuit.getConstraintCount()); }); - let extendedJsonInput = http_response_plaintext.concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); let headerName = toByte("content-type"); let headerValue = toByte("application/json; charset=utf-8"); @@ -96,6 +96,18 @@ describe("NIVC_HTTP", async () => { let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); it("HTTPParseAndExtract", async () => { + // fold 16 bytes at a time + let aes_gcm: CircuitSignals = { step_out: [] }; + console.log("DATA_BYTES", DATA_BYTES); + + for (let i = 0; i < (DATA_BYTES / 16); i++) { + // off by one here + let pt = http_response_plaintext.slice(i * 16, i * 16 +16); + console.log("pt", pt); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: Array(DATA_BYTES * 2 + 4).fill(0) }, ["step_out"]); + } + let out = aes_gcm.step_out as number[]; + let extendedJsonInput = out.slice(0, DATA_BYTES).concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); let lockHeader = await lockHeaderCircuit.compute({ step_in: parseAndLockStartLine.step_out, header: headerNamePadded, headerNameLength: headerName.length, value: headerValuePadded, headerValueLength: headerValue.length }, ["step_out"]); From 448a3e148ef69e58be64582b9507d4fa8a7ec2c4 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 14:37:22 -0600 Subject: [PATCH 12/21] initial rework of aes-gctr --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 71 +++++++++++++++------- circuits/test/full/full.test.ts | 22 ++++--- 2 files changed, 62 insertions(+), 31 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 9a0892a..04160c4 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -5,10 +5,15 @@ include "../../utils/array.circom"; // Compute AES-GCTR -template AESGCTRFOLD(DATA_BYTES) { - - assert(DATA_BYTES % 16 == 0); - var TOTAL_BYTES_ACROSS_NIVC = (DATA_BYTES * 2) + 4; +template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { + // ------------------------------------------------------------------------------------------------------------------ // + // ~~ Set sizes at compile time ~~ + assert(DATA_BYTES % 16 == 0); + // Total number of variables in the parser for each byte of data + 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 key[16]; signal input iv[12]; @@ -25,7 +30,7 @@ template AESGCTRFOLD(DATA_BYTES) { // We extract the number from the 4 byte word counter component last_counter_bits = BytesToBits(4); for(var i = 0; i < 4; i ++) { - last_counter_bits.in[i] <== step_in[DATA_BYTES*2 + i]; + last_counter_bits.in[i] <== step_in[DATA_BYTES * 2 + i]; } component last_counter_num = Bits2Num(32); // pass in reverse order @@ -35,14 +40,19 @@ template AESGCTRFOLD(DATA_BYTES) { counter <== last_counter_num.out - 1; + // TODO (Colin): We can't call this `WriteToIndex` array this many times, it is too expensive. // write new plain text block. - signal plainTextAccumulator[TOTAL_BYTES_ACROSS_NIVC]; - component writeToIndex = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 16); - writeToIndex.array_to_write_to <== step_in; + signal prevAccumulatedPlaintext[DATA_BYTES]; + for(var i = 0 ; i < DATA_BYTES ; i++) { + prevAccumulatedPlaintext[i] <== step_in[i]; + } + signal nextAccumulatedPlaintext[DATA_BYTES]; + component writeToIndex = WriteToIndex(DATA_BYTES, 16); + writeToIndex.array_to_write_to <== prevAccumulatedPlaintext; writeToIndex.array_to_write_at_index <== plainText; writeToIndex.index <== counter * 16; - writeToIndex.out ==> plainTextAccumulator; - + writeToIndex.out ==> nextAccumulatedPlaintext; + // folds one block component aes = AESGCTRFOLDABLE(); aes.key <== key; @@ -51,22 +61,37 @@ template AESGCTRFOLD(DATA_BYTES) { aes.plainText <== plainText; for(var i = 0; i < 4; i++) { - aes.lastCounter[i] <== step_in[DATA_BYTES*2 + i]; + aes.lastCounter[i] <== step_in[DATA_BYTES * 2 + i]; } // accumulate cipher text - signal cipherTextAccumulator[TOTAL_BYTES_ACROSS_NIVC]; - component writeCipherText = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 16); - writeCipherText.array_to_write_to <== plainTextAccumulator; + signal prevAccumulatedCiphertext[DATA_BYTES]; + for(var i = 0 ; i < DATA_BYTES ; i++) { + prevAccumulatedCiphertext[i] <== step_in[DATA_BYTES + i]; + } + signal nextAccumulatedCiphertext[DATA_BYTES]; + component writeCipherText = WriteToIndex(DATA_BYTES, 16); + writeCipherText.array_to_write_to <== prevAccumulatedCiphertext; writeCipherText.array_to_write_at_index <== aes.cipherText; - writeCipherText.index <== DATA_BYTES + counter * 16; - writeCipherText.out ==> cipherTextAccumulator; + writeCipherText.index <== counter * 16; + writeCipherText.out ==> nextAccumulatedCiphertext; + + for(var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { + if(i < DATA_BYTES) { + step_out[i] <== nextAccumulatedPlaintext[i]; + } else if(i < 2 * DATA_BYTES) { + step_out[i] <== nextAccumulatedCiphertext[i - DATA_BYTES]; + } else if(i < 2 * DATA_BYTES + 4) { + step_out[i] <== aes.counter[i - (2 * DATA_BYTES)]; + } + } // get counter - signal counterAccumulator[TOTAL_BYTES_ACROSS_NIVC]; - component writeCounter = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 4); - writeCounter.array_to_write_to <== cipherTextAccumulator; - writeCounter.array_to_write_at_index <== aes.counter; - writeCounter.index <== DATA_BYTES*2; - writeCounter.out ==> step_out; -} \ No newline at end of file + // signal counterAccumulator[TOTAL_BYTES_ACROSS_NIVC]; + // component writeCounter = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 4); + // writeCounter.array_to_write_to <== cipherTextAccumulator; + // writeCounter.array_to_write_at_index <== aes.counter; + // writeCounter.index <== DATA_BYTES*2; + // writeCounter.out ==> step_out; + +} diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index 164dd7a..fcef800 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -62,28 +62,29 @@ describe("NIVC_FULL", async () => { aesCircuit = await circomkit.WitnessTester("AESGCTRFOLD", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [DATA_BYTES], + params: [DATA_BYTES, MAX_STACK_HEIGHT], }); + // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); // TODO (Colin): This is at 1.3M constraints... httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { file: "http/nivc/parse_and_lock_start_line", template: "ParseAndLockStartLine", params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH], }); - console.log("#constraints:", await httpParseAndLockStartLineCircuit.getConstraintCount()); + console.log("#constraints (HTTP-PARSE-AND-LOCK-START-LINE):", await httpParseAndLockStartLineCircuit.getConstraintCount()); lockHeaderCircuit = await circomkit.WitnessTester(`LockHeader`, { file: "http/nivc/lock_header", template: "LockHeader", params: [DATA_BYTES, MAX_STACK_HEIGHT, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH], }); - console.log("#constraints:", await lockHeaderCircuit.getConstraintCount()); + console.log("#constraints (HTTP-LOCK-HEADER):", await lockHeaderCircuit.getConstraintCount()); bodyMaskCircuit = await circomkit.WitnessTester(`BodyMask`, { file: "http/nivc/body_mask", template: "HTTPMaskBodyNIVC", params: [DATA_BYTES, MAX_STACK_HEIGHT], }); - console.log("#constraints:", await bodyMaskCircuit.getConstraintCount()); + console.log("#constraints (HTTP-BODY-MASK):", await bodyMaskCircuit.getConstraintCount()); }); @@ -95,18 +96,23 @@ describe("NIVC_FULL", async () => { let beginningPadded = beginning.concat(Array(MAX_BEGINNING_LENGTH - beginning.length).fill(0)); let middlePadded = middle.concat(Array(MAX_MIDDLE_LENGTH - middle.length).fill(0)); let finalPadded = final.concat(Array(MAX_FINAL_LENGTH - final.length).fill(0)); - it("HTTPParseAndExtract", async () => { + it("NIVC_CHAIN", async () => { // fold 16 bytes at a time let aes_gcm: CircuitSignals = { step_out: [] }; console.log("DATA_BYTES", DATA_BYTES); - for (let i = 0; i < (DATA_BYTES / 16); i++) { + // Run the 0th chunk of plaintext + const init_nivc_input = Array(TOTAL_BYTES_ACROSS_NIVC).fill(0); // Blank array to write chunks to and pass through NIVC chain + let pt = http_response_plaintext.slice(16, 16 + 16); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); + for (let i = 1; i < (DATA_BYTES / 16); i++) { // off by one here - let pt = http_response_plaintext.slice(i * 16, i * 16 +16); + let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); console.log("pt", pt); - aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: Array(DATA_BYTES * 2 + 4).fill(0) }, ["step_out"]); + aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); } let out = aes_gcm.step_out as number[]; + console.log(JSON.stringify(out)); let extendedJsonInput = out.slice(0, DATA_BYTES).concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); From ea59a6d07ef5371dc9fc88b30b0a7cd5d6d9136a Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 14:37:49 -0600 Subject: [PATCH 13/21] fix: full test passes Also reduced constraints on AESGCTR --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 11 +---------- circuits/test/full/full.test.ts | 5 +++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 04160c4..869bb79 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -38,7 +38,7 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { last_counter_num.in[i] <== last_counter_bits.out[31 - i]; } - counter <== last_counter_num.out - 1; + counter <== last_counter_num.out; // TODO (Colin): We can't call this `WriteToIndex` array this many times, it is too expensive. // write new plain text block. @@ -85,13 +85,4 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { step_out[i] <== aes.counter[i - (2 * DATA_BYTES)]; } } - - // get counter - // signal counterAccumulator[TOTAL_BYTES_ACROSS_NIVC]; - // component writeCounter = WriteToIndex(TOTAL_BYTES_ACROSS_NIVC, 4); - // writeCounter.array_to_write_to <== cipherTextAccumulator; - // writeCounter.array_to_write_at_index <== aes.counter; - // writeCounter.index <== DATA_BYTES*2; - // writeCounter.out ==> step_out; - } diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index fcef800..b04995a 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -64,7 +64,7 @@ describe("NIVC_FULL", async () => { template: "AESGCTRFOLD", params: [DATA_BYTES, MAX_STACK_HEIGHT], }); - // console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); // TODO (Colin): This is at 1.3M constraints... + console.log("#constraints (AES-GCTR):", await aesCircuit.getConstraintCount()); httpParseAndLockStartLineCircuit = await circomkit.WitnessTester(`ParseAndLockStartLine`, { file: "http/nivc/parse_and_lock_start_line", template: "ParseAndLockStartLine", @@ -103,7 +103,8 @@ describe("NIVC_FULL", async () => { // Run the 0th chunk of plaintext const init_nivc_input = Array(TOTAL_BYTES_ACROSS_NIVC).fill(0); // Blank array to write chunks to and pass through NIVC chain - let pt = http_response_plaintext.slice(16, 16 + 16); + let pt = http_response_plaintext.slice(0, 16); + console.log("pt", pt); aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); for (let i = 1; i < (DATA_BYTES / 16); i++) { // off by one here From e116729681b57116f7f033285bce4bd496474391 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 16:53:31 -0600 Subject: [PATCH 14/21] fix: tests --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 16 ++-- circuits/aes-gctr-nivc.circom | 2 +- .../test/aes-gcm/nivc/aes-gctr-nivc.test.ts | 86 +++++++++++-------- circuits/test/full/full.test.ts | 14 +-- 4 files changed, 67 insertions(+), 51 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 869bb79..6f7852b 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -25,7 +25,7 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { // step_in[DATA_BYTES_LEN*2..DATA_BYTES*2+4] => accumulate counter signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; signal output step_out[TOTAL_BYTES_ACROSS_NIVC]; - signal counter; + // We extract the number from the 4 byte word counter component last_counter_bits = BytesToBits(4); @@ -37,10 +37,10 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { for (var i = 0; i< 32; i++){ last_counter_num.in[i] <== last_counter_bits.out[31 - i]; } + signal index <== last_counter_num.out - 1; - counter <== last_counter_num.out; + // TODO (Colin): We can probably make a template that writes to two multiple arrays at once that saves us even more constraints here instead of just using the `WriteToIndex` twice - // TODO (Colin): We can't call this `WriteToIndex` array this many times, it is too expensive. // write new plain text block. signal prevAccumulatedPlaintext[DATA_BYTES]; for(var i = 0 ; i < DATA_BYTES ; i++) { @@ -50,8 +50,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { component writeToIndex = WriteToIndex(DATA_BYTES, 16); writeToIndex.array_to_write_to <== prevAccumulatedPlaintext; writeToIndex.array_to_write_at_index <== plainText; - writeToIndex.index <== counter * 16; - writeToIndex.out ==> nextAccumulatedPlaintext; + writeToIndex.index <== index * 16; + nextAccumulatedPlaintext <== writeToIndex.out; // folds one block component aes = AESGCTRFOLDABLE(); @@ -73,8 +73,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { component writeCipherText = WriteToIndex(DATA_BYTES, 16); writeCipherText.array_to_write_to <== prevAccumulatedCiphertext; writeCipherText.array_to_write_at_index <== aes.cipherText; - writeCipherText.index <== counter * 16; - writeCipherText.out ==> nextAccumulatedCiphertext; + writeCipherText.index <== index * 16; + nextAccumulatedCiphertext <== writeCipherText.out; for(var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { if(i < DATA_BYTES) { @@ -83,6 +83,8 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { step_out[i] <== nextAccumulatedCiphertext[i - DATA_BYTES]; } else if(i < 2 * DATA_BYTES + 4) { step_out[i] <== aes.counter[i - (2 * DATA_BYTES)]; + } else { + step_out[i] <== 0; } } } diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom index 2ec7580..6fb0b31 100644 --- a/circuits/aes-gctr-nivc.circom +++ b/circuits/aes-gctr-nivc.circom @@ -3,4 +3,4 @@ pragma circom 2.1.9; include "aes-gcm/nivc/aes-gctr-nivc.circom"; // the circomkit tests become unhappy when there is a main. -component main { public [step_in] } = AESGCTRFOLD(48); \ No newline at end of file +component main { public [step_in] } = AESGCTRFOLD(1024, 5); \ No newline at end of file diff --git a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts index 4b63918..6ebd2bb 100644 --- a/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts +++ b/circuits/test/aes-gcm/nivc/aes-gctr-nivc.test.ts @@ -2,26 +2,36 @@ import { assert } from "chai"; import { WitnessTester } from "circomkit"; import { circomkit } from "../../common"; +const MAX_STACK_HEIGHT = 0; + describe("aes-gctr-nivc", () => { let circuit_one_block: WitnessTester<["key", "iv", "plainText", "aad", "step_in"], ["step_out"]>; + + const DATA_BYTES_0 = 16; + const TOTAL_BYTES_ACROSS_NIVC_0 = DATA_BYTES_0 * (MAX_STACK_HEIGHT + 2 + 1) + 1; + it("all correct for self generated single zero pt block case", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [16], // input len is 16 bytes + params: [DATA_BYTES_0, MAX_STACK_HEIGHT], // input len is 16 bytes }); - let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let key = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let plainText = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; + let iv = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let ct = [0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(32).fill(0x00).concat(counter); + const counter = [0x00, 0x00, 0x00, 0x01]; + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_0 + index] = value; + }); let expected = plainText.concat(ct).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_0 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); }); @@ -30,45 +40,55 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [16], // input len is 16 bytes + params: [DATA_BYTES_0, MAX_STACK_HEIGHT], // input len is 16 bytes }); - - let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + + let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; let plainText = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; - let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; - let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let ct = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(32).fill(0x00).concat(counter); + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_0).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_0 + index] = value; + }); let expected = plainText.concat(ct).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_0 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); }); + const DATA_BYTES_1 = 32; + const TOTAL_BYTES_ACROSS_NIVC_1 = DATA_BYTES_1 * (MAX_STACK_HEIGHT + 2 + 1) + 1; + + let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + let plainText1 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; + let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; + let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; + let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; + let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; it("all correct for self generated two block case first fold", async () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [DATA_BYTES_1, MAX_STACK_HEIGHT], // input len is 32 bytes }); - let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; - let plainText1 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; - let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; - let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; - let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; - let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; - const counter = [0x00, 0x00, 0x00, 0x01]; - const step_in = new Array(64).fill(0x00).concat(counter); + const step_in = new Array(TOTAL_BYTES_ACROSS_NIVC_1).fill(0x00); + counter.forEach((value, index) => { + step_in[2 * DATA_BYTES_1 + index] = value; + }); let expected = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat([0x00, 0x00, 0x00, 0x02]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText1, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); @@ -78,21 +98,15 @@ describe("aes-gctr-nivc", () => { circuit_one_block = await circomkit.WitnessTester("aes-gcm-fold", { file: "aes-gcm/nivc/aes-gctr-nivc", template: "AESGCTRFOLD", - params: [32], // input len is 32 bytes + params: [DATA_BYTES_1, MAX_STACK_HEIGHT], // input len is 32 bytes }); - let zero_block = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let key = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; - let plainText1 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; - let plainText2 = [0x74, 0x65, 0x73, 0x74, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30]; - let iv = [0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31]; - let aad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; - let ct_part1 = [0x29, 0x29, 0xd2, 0xbb, 0x1a, 0xe9, 0x48, 0x04, 0x40, 0x2b, 0x8e, 0x77, 0x6e, 0x0d, 0x33, 0x56]; - let ct_part2 = [0x26, 0x75, 0x65, 0x30, 0x71, 0x3e, 0x4c, 0x06, 0x5a, 0xf1, 0xd3, 0xc4, 0xf5, 0x6e, 0x02, 0x04]; - const counter = [0x00, 0x00, 0x00, 0x02]; - const step_in = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat(counter); + let step_in = plainText1.concat(zero_block).concat(ct_part1).concat(zero_block).concat(counter); + step_in = step_in.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - step_in.length).fill(0)); + let expected = plainText1.concat(plainText2).concat(ct_part1).concat(ct_part2).concat([0x00, 0x00, 0x00, 0x03]); + expected = expected.concat(new Array(TOTAL_BYTES_ACROSS_NIVC_1 - expected.length).fill(0)); const witness = await circuit_one_block.compute({ key: key, iv: iv, plainText: plainText2, aad: aad, step_in: step_in }, ["step_out"]) assert.deepEqual(witness.step_out, expected.map(BigInt)); diff --git a/circuits/test/full/full.test.ts b/circuits/test/full/full.test.ts index b04995a..cde3d60 100644 --- a/circuits/test/full/full.test.ts +++ b/circuits/test/full/full.test.ts @@ -88,7 +88,7 @@ describe("NIVC_FULL", async () => { }); - let headerName = toByte("content-type"); + let headerName = toByte("content-type") let headerValue = toByte("application/json; charset=utf-8"); let headerNamePadded = headerName.concat(Array(MAX_HEADER_NAME_LENGTH - headerName.length).fill(0)); @@ -99,21 +99,21 @@ describe("NIVC_FULL", async () => { it("NIVC_CHAIN", async () => { // fold 16 bytes at a time let aes_gcm: CircuitSignals = { step_out: [] }; - console.log("DATA_BYTES", DATA_BYTES); + // console.log("DATA_BYTES", DATA_BYTES); // Run the 0th chunk of plaintext - const init_nivc_input = Array(TOTAL_BYTES_ACROSS_NIVC).fill(0); // Blank array to write chunks to and pass through NIVC chain + const counter = [0x00, 0x00, 0x00, 0x01]; + const init_nivc_input = new Array(TOTAL_BYTES_ACROSS_NIVC).fill(0x00); + counter.forEach((value, index) => { + init_nivc_input[2 * DATA_BYTES + index] = value; + }); let pt = http_response_plaintext.slice(0, 16); - console.log("pt", pt); aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: init_nivc_input }, ["step_out"]); for (let i = 1; i < (DATA_BYTES / 16); i++) { - // off by one here let pt = http_response_plaintext.slice(i * 16, i * 16 + 16); - console.log("pt", pt); aes_gcm = await aesCircuit.compute({ key: Array(16).fill(0), iv: Array(12).fill(0), plainText: pt, aad: Array(16).fill(0), step_in: aes_gcm.step_out }, ["step_out"]); } let out = aes_gcm.step_out as number[]; - console.log(JSON.stringify(out)); let extendedJsonInput = out.slice(0, DATA_BYTES).concat(Array(Math.max(0, TOTAL_BYTES_ACROSS_NIVC - http_response_plaintext.length)).fill(0)); let parseAndLockStartLine = await httpParseAndLockStartLineCircuit.compute({ step_in: extendedJsonInput, beginning: beginningPadded, beginning_length: beginning.length, middle: middlePadded, middle_length: middle.length, final: finalPadded, final_length: final.length }, ["step_out"]); From 8c5f2d3cec7160fb0daf228192997685f11a81cb Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 17:07:57 -0600 Subject: [PATCH 15/21] small optimization --- circuits/aes-gcm/nivc/aes-gctr-nivc.circom | 129 +++++++++++++++++---- 1 file changed, 105 insertions(+), 24 deletions(-) diff --git a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom index 6f7852b..6d17213 100644 --- a/circuits/aes-gcm/nivc/aes-gctr-nivc.circom +++ b/circuits/aes-gcm/nivc/aes-gctr-nivc.circom @@ -38,20 +38,6 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { last_counter_num.in[i] <== last_counter_bits.out[31 - i]; } signal index <== last_counter_num.out - 1; - - // TODO (Colin): We can probably make a template that writes to two multiple arrays at once that saves us even more constraints here instead of just using the `WriteToIndex` twice - - // write new plain text block. - signal prevAccumulatedPlaintext[DATA_BYTES]; - for(var i = 0 ; i < DATA_BYTES ; i++) { - prevAccumulatedPlaintext[i] <== step_in[i]; - } - signal nextAccumulatedPlaintext[DATA_BYTES]; - component writeToIndex = WriteToIndex(DATA_BYTES, 16); - writeToIndex.array_to_write_to <== prevAccumulatedPlaintext; - writeToIndex.array_to_write_at_index <== plainText; - writeToIndex.index <== index * 16; - nextAccumulatedPlaintext <== writeToIndex.out; // folds one block component aes = AESGCTRFOLDABLE(); @@ -64,23 +50,29 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { aes.lastCounter[i] <== step_in[DATA_BYTES * 2 + i]; } - // accumulate cipher text + + // Write out the plaintext and ciphertext to our accumulation arrays, both at once. + signal prevAccumulatedPlaintext[DATA_BYTES]; + for(var i = 0 ; i < DATA_BYTES ; i++) { + prevAccumulatedPlaintext[i] <== step_in[i]; + } signal prevAccumulatedCiphertext[DATA_BYTES]; for(var i = 0 ; i < DATA_BYTES ; i++) { prevAccumulatedCiphertext[i] <== step_in[DATA_BYTES + i]; - } - signal nextAccumulatedCiphertext[DATA_BYTES]; - component writeCipherText = WriteToIndex(DATA_BYTES, 16); - writeCipherText.array_to_write_to <== prevAccumulatedCiphertext; - writeCipherText.array_to_write_at_index <== aes.cipherText; - writeCipherText.index <== index * 16; - nextAccumulatedCiphertext <== writeCipherText.out; + } + component nextTexts = WriteToIndexForTwoArrays(DATA_BYTES, 16); + nextTexts.first_array_to_write_to <== prevAccumulatedPlaintext; + nextTexts.second_array_to_write_to <== prevAccumulatedCiphertext; + nextTexts.first_array_to_write_at_index <== plainText; + nextTexts.second_array_to_write_at_index <== aes.cipherText; + nextTexts.index <== index * 16; + for(var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) { if(i < DATA_BYTES) { - step_out[i] <== nextAccumulatedPlaintext[i]; + step_out[i] <== nextTexts.outFirst[i]; } else if(i < 2 * DATA_BYTES) { - step_out[i] <== nextAccumulatedCiphertext[i - DATA_BYTES]; + step_out[i] <== nextTexts.outSecond[i - DATA_BYTES]; } else if(i < 2 * DATA_BYTES + 4) { step_out[i] <== aes.counter[i - (2 * DATA_BYTES)]; } else { @@ -88,3 +80,92 @@ template AESGCTRFOLD(DATA_BYTES, MAX_STACK_HEIGHT) { } } } + + + +template WriteToIndexForTwoArrays(m, n) { + signal input first_array_to_write_to[m]; + signal input second_array_to_write_to[m]; + signal input first_array_to_write_at_index[n]; + signal input second_array_to_write_at_index[n]; + signal input index; + + signal output outFirst[m]; + signal output outSecond[m]; + + assert(m >= n); + + // Note: this is underconstrained, we need to constrain that index + n <= m + // Need to constrain that index + n <= m -- can't be an assertion, because uses a signal + // ------------------------- // + + // Here, we get an array of ALL zeros, except at the `index` AND `index + n` + // beginning-------^^^^^ end---^^^^^^^^^ + signal indexMatched[m]; + component indexBegining[m]; + component indexEnding[m]; + for(var i = 0 ; i < m ; i++) { + indexBegining[i] = IsZero(); + indexBegining[i].in <== i - index; + indexEnding[i] = IsZero(); + indexEnding[i].in <== i - (index + n); + indexMatched[i] <== indexBegining[i].out + indexEnding[i].out; + } + + // E.g., index == 31, m == 160, n == 16 + // => indexMatch[31] == 1; + // => indexMatch[47] == 1; + // => otherwise, all 0. + + signal accum[m]; + accum[0] <== indexMatched[0]; + + component writeAt = IsZero(); + writeAt.in <== accum[0] - 1; + + component orFirst = OR(); + orFirst.a <== (writeAt.out * first_array_to_write_at_index[0]); + orFirst.b <== (1 - writeAt.out) * first_array_to_write_to[0]; + outFirst[0] <== orFirst.out; + + component orSecond = OR(); + orSecond.a <== (writeAt.out * second_array_to_write_at_index[0]); + orSecond.b <== (1 - writeAt.out) * second_array_to_write_to[0]; + outSecond[0] <== orSecond.out; + // IF accum == 1 then { array_to_write_at } ELSE IF accum != 1 then { array to write_to } + var accum_index = accum[0]; + + component writeSelector[m - 1]; + component indexSelectorFirst[m - 1]; + component indexSelectorSecond[m - 1]; + component orsFirst[m-1]; + component orsSecond[m-1]; + for(var i = 1 ; i < m ; i++) { + // accum will be 1 at all indices where we want to write the new array + accum[i] <== accum[i-1] + indexMatched[i]; + writeSelector[i-1] = IsZero(); + writeSelector[i-1].in <== accum[i] - 1; + // IsZero(accum[i] - 1); --> tells us we are in the range where we want to write the new array + + indexSelectorFirst[i-1] = IndexSelector(n); + indexSelectorFirst[i-1].index <== accum_index; + indexSelectorFirst[i-1].in <== first_array_to_write_at_index; + + indexSelectorSecond[i-1] = IndexSelector(n); + indexSelectorSecond[i-1].index <== accum_index; + indexSelectorSecond[i-1].in <== second_array_to_write_at_index; + // When accum is not zero, out is array_to_write_at_index, otherwise it is array_to_write_to + + orsFirst[i-1] = OR(); + orsFirst[i-1].a <== (writeSelector[i-1].out * indexSelectorFirst[i-1].out); + orsFirst[i-1].b <== (1 - writeSelector[i-1].out) * first_array_to_write_to[i]; + outFirst[i] <== orsFirst[i-1].out; + + orsSecond[i-1] = OR(); + orsSecond[i-1].a <== (writeSelector[i-1].out * indexSelectorSecond[i-1].out); + orsSecond[i-1].b <== (1 - writeSelector[i-1].out) * second_array_to_write_to[i]; + outSecond[i] <== orsSecond[i-1].out; + + accum_index += writeSelector[i-1].out; + } +} From 31493c8a0c2e320a8d704b60a7856bc9e7af53d0 Mon Sep 17 00:00:00 2001 From: Colin Roberts Date: Fri, 1 Nov 2024 18:04:34 -0600 Subject: [PATCH 16/21] circuit build set --- .github/workflows/artifacts.yaml | 51 +++++++++---------- .github/workflows/release.yaml | 23 +++++---- .gitignore | 2 + Makefile | 35 +++++++++++++ .../target_1024b/aes_gctr_nivc_1024b.circom | 6 +++ .../target_1024b/http_body_mask_1024b.circom | 6 +++ .../http_lock_header_1024b.circom | 5 ++ ...http_parse_and_lock_start_line_1024b.built | 0 ...ttp_parse_and_lock_start_line_1024b.circom | 5 ++ .../json_extract_value_1024b.circom | 5 ++ .../json_mask_array_index_1024b.circom | 5 ++ .../json_mask_object_1024b.circom | 5 ++ builds/target_1024b/json_parse_1024b.circom | 6 +++ circuits/aes-gctr-nivc.circom | 6 --- circuits/extract_value.circom | 5 -- circuits/http_body_mask.circom | 6 --- circuits/http_lock_header.circom | 5 -- .../http_parse_and_lock_start_line.circom | 5 -- circuits/json_mask_array_index.circom | 5 -- circuits/json_mask_object.circom | 5 -- circuits/json_parse.circom | 6 --- 21 files changed, 118 insertions(+), 79 deletions(-) create mode 100644 Makefile create mode 100644 builds/target_1024b/aes_gctr_nivc_1024b.circom create mode 100644 builds/target_1024b/http_body_mask_1024b.circom create mode 100644 builds/target_1024b/http_lock_header_1024b.circom create mode 100644 builds/target_1024b/http_parse_and_lock_start_line_1024b.built create mode 100644 builds/target_1024b/http_parse_and_lock_start_line_1024b.circom create mode 100644 builds/target_1024b/json_extract_value_1024b.circom create mode 100644 builds/target_1024b/json_mask_array_index_1024b.circom create mode 100644 builds/target_1024b/json_mask_object_1024b.circom create mode 100644 builds/target_1024b/json_parse_1024b.circom delete mode 100644 circuits/aes-gctr-nivc.circom delete mode 100644 circuits/extract_value.circom delete mode 100644 circuits/http_body_mask.circom delete mode 100644 circuits/http_lock_header.circom delete mode 100644 circuits/http_parse_and_lock_start_line.circom delete mode 100644 circuits/json_mask_array_index.circom delete mode 100644 circuits/json_mask_object.circom delete mode 100644 circuits/json_parse.circom diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml index 4f6a2b6..06c5daa 100644 --- a/.github/workflows/artifacts.yaml +++ b/.github/workflows/artifacts.yaml @@ -17,21 +17,19 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 2 # Fetch two commits to get the base branch + fetch-depth: 2 - name: Fetch main branch run: | git fetch origin main + - name: Compare package.json version with main id: version_check run: | - # Extract version from package.json in PR branch PR_VERSION=$(jq -r .version package.json) - # Extract version from package.json in main branch MAIN_VERSION=$(git show origin/main:package.json | jq -r .version) echo "PR version: $PR_VERSION" echo "Main version: $MAIN_VERSION" - # Fail if versions match if [ "$PR_VERSION" == "$MAIN_VERSION" ]; then echo "Error: package.json version has not been updated in this PR." exit 1 @@ -41,12 +39,13 @@ jobs: build: runs-on: ubuntu-latest + needs: check-version steps: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Need full history to compare with previous release + fetch-depth: 0 - name: Install Protocol Buffers run: | @@ -87,36 +86,34 @@ jobs: VERSION=$(node -p "require('./package.json').version") echo "VERSION=$VERSION" >> $GITHUB_ENV - - name: Compile Circom circuits + - name: Build circuits using Makefile run: | - mkdir -p artifacts - for circuit in circuits/*.circom; do - if [ -f "$circuit" ]; then - filename=$(basename "$circuit" .circom) - output_dir="artifacts/$filename" - mkdir -p "$output_dir" - - echo "Processing $filename..." + make debug # Show what will be processed + make build # Build the circuits - # Run circom compilation - circom "$circuit" --r1cs --wasm -o "$output_dir" -l node_modules - - # Run witness calculator build - build-circuit "$circuit" "$output_dir/$filename.bin" -l node_modules + - name: Create release artifacts + run: | + # Get the list of target directories + for target_dir in builds/target_*b; do + if [ -d "$target_dir/artifacts" ]; then + # Extract the target size from the directory name + target_size=$(basename "$target_dir") + + echo "Creating archive for $target_size" + # Create zip file for this target size + ( cd "$target_dir/artifacts" && \ + zip -r "../../../circom-artifacts-${target_size}-v${{ env.VERSION }}.zip" . ) fi done - - name: Create release artifacts - run: | - cd artifacts - zip -r ../circom-artifacts-v${{ env.VERSION }}.zip ./* - cd .. + - name: Clean build artifacts + if: always() + run: make clean - # Upload artifacts for PR - - name: Upload artifacts for PR + - name: Upload artifacts if: github.event_name == 'pull_request' uses: actions/upload-artifact@v4 with: name: circom-artifacts-v${{ env.VERSION }} - path: circom-artifacts-v${{ env.VERSION }}.zip + path: circom-artifacts-*-v${{ env.VERSION }}.zip retention-days: 5 \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c62310e..f68e115 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,4 +1,3 @@ -# .github/workflows/release.yml name: Release on: @@ -50,20 +49,26 @@ jobs: uses: actions/download-artifact@v4 with: name: circom-artifacts-v${{ env.VERSION }} - path: . + path: ./artifacts github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ env.run_id }} + - name: Prepare Release Notes + run: | + echo "Automated release of compiled Circom circuits" > release_notes.md + echo "Version: ${{ env.VERSION }}" >> release_notes.md + echo "Commit: ${{ github.sha }}" >> release_notes.md + echo "\nArtifacts included:" >> release_notes.md + for zip in artifacts/circom-artifacts-*-v${{ env.VERSION }}.zip; do + basename "$zip" >> release_notes.md + done - # Add artifacts to existing release - - name: Upload Release Asset + # Create release with all artifact files + - name: Upload Release Assets uses: softprops/action-gh-release@v2 with: - files: circom-artifacts-v${{ env.VERSION }}.zip + files: artifacts/circom-artifacts-*-v${{ env.VERSION }}.zip tag_name: v${{ env.VERSION }} - body: | - Automated release of compiled Circom circuits - Version: ${{ env.VERSION }} - Commit: ${{ github.sha }} + body_path: release_notes.md env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 680faa2..f70f723 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ ir_log/* log_input_signals.txt *.bin *.r1cs +builds/**/*.bin +builds/**/*.r1cs \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a3a15cf --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +# Find all target directories +TARGET_DIRS := $(wildcard builds/target_*b) + +# Find all .circom files in those directories +CIRCOM_FILES := $(wildcard $(addsuffix /*_*b.circom,$(TARGET_DIRS))) + +# Create artifacts directories +$(shell mkdir -p $(addsuffix /artifacts,$(TARGET_DIRS))) + +# Default target +.PHONY: all clean +all: build + +# Build target +.PHONY: build +build: + @for circuit in $(CIRCOM_FILES); do \ + echo "Processing $${circuit}..."; \ + circom "$${circuit}" --r1cs -o "$$(dirname $${circuit})/artifacts" -l node_modules; \ + build-circuit "$${circuit}" "$$(dirname $${circuit})/artifacts/$$(basename $${circuit} .circom).bin" -l node_modules; \ + done + +# Clean target +clean: + rm -rf $(addsuffix /artifacts,$(TARGET_DIRS)) + +# Debug target to show what files were found +.PHONY: debug +debug: + @echo "Found directories:" + @echo $(TARGET_DIRS) + @echo "\nFound circom files:" + @echo $(CIRCOM_FILES) + @echo "\nArtifacts will be generated in:" + @echo $(addsuffix /artifacts,$(TARGET_DIRS)) \ No newline at end of file diff --git a/builds/target_1024b/aes_gctr_nivc_1024b.circom b/builds/target_1024b/aes_gctr_nivc_1024b.circom new file mode 100644 index 0000000..ae0ccf2 --- /dev/null +++ b/builds/target_1024b/aes_gctr_nivc_1024b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/aes-gcm/nivc/aes-gctr-nivc.circom"; + +// the circomkit tests become unhappy when there is a main. +component main { public [step_in] } = AESGCTRFOLD(1024, 10); \ No newline at end of file diff --git a/builds/target_1024b/http_body_mask_1024b.circom b/builds/target_1024b/http_body_mask_1024b.circom new file mode 100644 index 0000000..ea474a2 --- /dev/null +++ b/builds/target_1024b/http_body_mask_1024b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/body_mask.circom"; + +component main { public [step_in] } = HTTPMaskBodyNIVC(1024, 10); + diff --git a/builds/target_1024b/http_lock_header_1024b.circom b/builds/target_1024b/http_lock_header_1024b.circom new file mode 100644 index 0000000..fc3d5b3 --- /dev/null +++ b/builds/target_1024b/http_lock_header_1024b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/lock_header.circom"; + +component main { public [step_in] } = LockHeader(1024, 10, 50, 100); \ No newline at end of file diff --git a/builds/target_1024b/http_parse_and_lock_start_line_1024b.built b/builds/target_1024b/http_parse_and_lock_start_line_1024b.built new file mode 100644 index 0000000..e69de29 diff --git a/builds/target_1024b/http_parse_and_lock_start_line_1024b.circom b/builds/target_1024b/http_parse_and_lock_start_line_1024b.circom new file mode 100644 index 0000000..c1150bc --- /dev/null +++ b/builds/target_1024b/http_parse_and_lock_start_line_1024b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/parse_and_lock_start_line.circom"; + +component main { public [step_in] } = ParseAndLockStartLine(1024, 10, 20, 20, 20); \ No newline at end of file diff --git a/builds/target_1024b/json_extract_value_1024b.circom b/builds/target_1024b/json_extract_value_1024b.circom new file mode 100644 index 0000000..7f4d122 --- /dev/null +++ b/builds/target_1024b/json_extract_value_1024b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/extractor.circom"; + +component main { public [step_in] } = MaskExtractFinal(1024, 10, 50); \ No newline at end of file diff --git a/builds/target_1024b/json_mask_array_index_1024b.circom b/builds/target_1024b/json_mask_array_index_1024b.circom new file mode 100644 index 0000000..d2793c8 --- /dev/null +++ b/builds/target_1024b/json_mask_array_index_1024b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskArrayIndexNIVC(1024, 10); \ No newline at end of file diff --git a/builds/target_1024b/json_mask_object_1024b.circom b/builds/target_1024b/json_mask_object_1024b.circom new file mode 100644 index 0000000..e91d812 --- /dev/null +++ b/builds/target_1024b/json_mask_object_1024b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskObjectNIVC(1024, 10, 10); diff --git a/builds/target_1024b/json_parse_1024b.circom b/builds/target_1024b/json_parse_1024b.circom new file mode 100644 index 0000000..4538d31 --- /dev/null +++ b/builds/target_1024b/json_parse_1024b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/parse.circom"; + +component main { public [step_in] } = JsonParseNIVC(1024, 10); + diff --git a/circuits/aes-gctr-nivc.circom b/circuits/aes-gctr-nivc.circom deleted file mode 100644 index 6fb0b31..0000000 --- a/circuits/aes-gctr-nivc.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "aes-gcm/nivc/aes-gctr-nivc.circom"; - -// the circomkit tests become unhappy when there is a main. -component main { public [step_in] } = AESGCTRFOLD(1024, 5); \ No newline at end of file diff --git a/circuits/extract_value.circom b/circuits/extract_value.circom deleted file mode 100644 index 8e3906b..0000000 --- a/circuits/extract_value.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/extractor.circom"; - -component main { public [step_in] } = MaskExtractFinal(49, 32, 32); \ No newline at end of file diff --git a/circuits/http_body_mask.circom b/circuits/http_body_mask.circom deleted file mode 100644 index fedbe20..0000000 --- a/circuits/http_body_mask.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/body_mask.circom"; - -component main { public [step_in] } = HTTPMaskBodyNIVC(48, 16); - diff --git a/circuits/http_lock_header.circom b/circuits/http_lock_header.circom deleted file mode 100644 index 0bb436e..0000000 --- a/circuits/http_lock_header.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/lock_header.circom"; - -component main { public [step_in] } = LockHeader(48, 16, 12, 16); \ No newline at end of file diff --git a/circuits/http_parse_and_lock_start_line.circom b/circuits/http_parse_and_lock_start_line.circom deleted file mode 100644 index f0ba8a5..0000000 --- a/circuits/http_parse_and_lock_start_line.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "http/nivc/parse_and_lock_start_line.circom"; - -component main { public [step_in] } = ParseAndLockStartLine(48, 16, 8, 3, 2); \ No newline at end of file diff --git a/circuits/json_mask_array_index.circom b/circuits/json_mask_array_index.circom deleted file mode 100644 index dfe2334..0000000 --- a/circuits/json_mask_array_index.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/masker.circom"; - -component main { public [step_in] } = JsonMaskArrayIndexNIVC(48, 16); \ No newline at end of file diff --git a/circuits/json_mask_object.circom b/circuits/json_mask_object.circom deleted file mode 100644 index 5f49944..0000000 --- a/circuits/json_mask_object.circom +++ /dev/null @@ -1,5 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/masker.circom"; - -component main { public [step_in] } = JsonMaskObjectNIVC(48, 16, 5); diff --git a/circuits/json_parse.circom b/circuits/json_parse.circom deleted file mode 100644 index 3204dff..0000000 --- a/circuits/json_parse.circom +++ /dev/null @@ -1,6 +0,0 @@ -pragma circom 2.1.9; - -include "json/nivc/parse.circom"; - -component main { public [step_in] } = JsonParseNIVC(48, 16); - From b11032e520438f2bebe0752fd78c287e9ed625f3 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 4 Nov 2024 15:52:51 +0700 Subject: [PATCH 17/21] chore: new other build files creates two new builds for 512 bytes and 256 bytes. Also runs wit calc in the CI tests whereas before it was just being installed in the artifacts jobs and being used. I double checked the artifact Job and the make file and believe that they will both correctly make separate zips for each build. There was also one miscellaneous empty file with a .built extension that i assumed was a mistake so i removed it. --- .github/workflows/artifacts.yaml | 7 ------- .github/workflows/test.yml | 13 ++++++++++++- .../http_parse_and_lock_start_line_1024b.built | 0 builds/target_256b/aes_gctr_nivc_256b.circom | 6 ++++++ builds/target_256b/http_body_mask_256b.circom | 6 ++++++ builds/target_256b/http_lock_header_256b.circom | 5 +++++ .../http_parse_and_lock_start_line_256b.circom | 5 +++++ builds/target_256b/json_extract_value_256b.circom | 5 +++++ .../target_256b/json_mask_array_index_256b.circom | 5 +++++ builds/target_256b/json_mask_object_256b.circom | 5 +++++ builds/target_256b/json_parse_256b.circom | 6 ++++++ builds/target_512b/aes_gctr_nivc_512b.circom | 6 ++++++ builds/target_512b/http_body_mask_512b.circom | 6 ++++++ builds/target_512b/http_lock_header_512b.circom | 5 +++++ .../http_parse_and_lock_start_line_512b.circom | 5 +++++ builds/target_512b/json_extract_value_512b.circom | 5 +++++ .../target_512b/json_mask_array_index_512b.circom | 5 +++++ builds/target_512b/json_mask_object_512b.circom | 5 +++++ builds/target_512b/json_parse_512b.circom | 6 ++++++ 19 files changed, 98 insertions(+), 8 deletions(-) delete mode 100644 builds/target_1024b/http_parse_and_lock_start_line_1024b.built create mode 100644 builds/target_256b/aes_gctr_nivc_256b.circom create mode 100644 builds/target_256b/http_body_mask_256b.circom create mode 100644 builds/target_256b/http_lock_header_256b.circom create mode 100644 builds/target_256b/http_parse_and_lock_start_line_256b.circom create mode 100644 builds/target_256b/json_extract_value_256b.circom create mode 100644 builds/target_256b/json_mask_array_index_256b.circom create mode 100644 builds/target_256b/json_mask_object_256b.circom create mode 100644 builds/target_256b/json_parse_256b.circom create mode 100644 builds/target_512b/aes_gctr_nivc_512b.circom create mode 100644 builds/target_512b/http_body_mask_512b.circom create mode 100644 builds/target_512b/http_lock_header_512b.circom create mode 100644 builds/target_512b/http_parse_and_lock_start_line_512b.circom create mode 100644 builds/target_512b/json_extract_value_512b.circom create mode 100644 builds/target_512b/json_mask_array_index_512b.circom create mode 100644 builds/target_512b/json_mask_object_512b.circom create mode 100644 builds/target_512b/json_parse_512b.circom diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml index 06c5daa..30cda10 100644 --- a/.github/workflows/artifacts.yaml +++ b/.github/workflows/artifacts.yaml @@ -69,13 +69,6 @@ jobs: sudo mv circom /usr/local/bin/ circom --version - - name: Install circom-witnesscalc - run: | - cd .. && git clone https://github.com/pluto/circom-witnesscalc.git - cd circom-witnesscalc - cargo install --path . - echo $(which build-circuit) - - name: Install Node.js dependencies run: | npm ci diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f89936c..7e112e2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,4 +36,15 @@ jobs: circom --version - name: Run tests - run: npm run test \ No newline at end of file + run: npm run test + + - name: Install circom-witnesscalc + run: | + cd .. && git clone https://github.com/pluto/circom-witnesscalc.git + cd circom-witnesscalc + cargo install --path . + echo $(which build-circuit) + + - name: Run build-circuit on target files + run: | + build-circuit builds/target_256b/*.circom \ No newline at end of file diff --git a/builds/target_1024b/http_parse_and_lock_start_line_1024b.built b/builds/target_1024b/http_parse_and_lock_start_line_1024b.built deleted file mode 100644 index e69de29..0000000 diff --git a/builds/target_256b/aes_gctr_nivc_256b.circom b/builds/target_256b/aes_gctr_nivc_256b.circom new file mode 100644 index 0000000..478c4b2 --- /dev/null +++ b/builds/target_256b/aes_gctr_nivc_256b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/aes-gcm/nivc/aes-gctr-nivc.circom"; + +// the circomkit tests become unhappy when there is a main. +component main { public [step_in] } = AESGCTRFOLD(256, 10); \ No newline at end of file diff --git a/builds/target_256b/http_body_mask_256b.circom b/builds/target_256b/http_body_mask_256b.circom new file mode 100644 index 0000000..ffb3b7e --- /dev/null +++ b/builds/target_256b/http_body_mask_256b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/body_mask.circom"; + +component main { public [step_in] } = HTTPMaskBodyNIVC(512, 10); + diff --git a/builds/target_256b/http_lock_header_256b.circom b/builds/target_256b/http_lock_header_256b.circom new file mode 100644 index 0000000..02d9dc9 --- /dev/null +++ b/builds/target_256b/http_lock_header_256b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/lock_header.circom"; + +component main { public [step_in] } = LockHeader(512, 10, 50, 100); \ No newline at end of file diff --git a/builds/target_256b/http_parse_and_lock_start_line_256b.circom b/builds/target_256b/http_parse_and_lock_start_line_256b.circom new file mode 100644 index 0000000..92c2bc8 --- /dev/null +++ b/builds/target_256b/http_parse_and_lock_start_line_256b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/parse_and_lock_start_line.circom"; + +component main { public [step_in] } = ParseAndLockStartLine(512, 10, 20, 20, 20); \ No newline at end of file diff --git a/builds/target_256b/json_extract_value_256b.circom b/builds/target_256b/json_extract_value_256b.circom new file mode 100644 index 0000000..da8db1f --- /dev/null +++ b/builds/target_256b/json_extract_value_256b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/extractor.circom"; + +component main { public [step_in] } = MaskExtractFinal(256, 10, 50); \ No newline at end of file diff --git a/builds/target_256b/json_mask_array_index_256b.circom b/builds/target_256b/json_mask_array_index_256b.circom new file mode 100644 index 0000000..83ebb08 --- /dev/null +++ b/builds/target_256b/json_mask_array_index_256b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskArrayIndexNIVC(256, 10); \ No newline at end of file diff --git a/builds/target_256b/json_mask_object_256b.circom b/builds/target_256b/json_mask_object_256b.circom new file mode 100644 index 0000000..b6bb1ef --- /dev/null +++ b/builds/target_256b/json_mask_object_256b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskObjectNIVC(256, 10, 10); diff --git a/builds/target_256b/json_parse_256b.circom b/builds/target_256b/json_parse_256b.circom new file mode 100644 index 0000000..c0f5e8c --- /dev/null +++ b/builds/target_256b/json_parse_256b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/parse.circom"; + +component main { public [step_in] } = JsonParseNIVC(256, 10); + diff --git a/builds/target_512b/aes_gctr_nivc_512b.circom b/builds/target_512b/aes_gctr_nivc_512b.circom new file mode 100644 index 0000000..07939ff --- /dev/null +++ b/builds/target_512b/aes_gctr_nivc_512b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/aes-gcm/nivc/aes-gctr-nivc.circom"; + +// the circomkit tests become unhappy when there is a main. +component main { public [step_in] } = AESGCTRFOLD(512, 10); \ No newline at end of file diff --git a/builds/target_512b/http_body_mask_512b.circom b/builds/target_512b/http_body_mask_512b.circom new file mode 100644 index 0000000..ffb3b7e --- /dev/null +++ b/builds/target_512b/http_body_mask_512b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/body_mask.circom"; + +component main { public [step_in] } = HTTPMaskBodyNIVC(512, 10); + diff --git a/builds/target_512b/http_lock_header_512b.circom b/builds/target_512b/http_lock_header_512b.circom new file mode 100644 index 0000000..02d9dc9 --- /dev/null +++ b/builds/target_512b/http_lock_header_512b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/lock_header.circom"; + +component main { public [step_in] } = LockHeader(512, 10, 50, 100); \ No newline at end of file diff --git a/builds/target_512b/http_parse_and_lock_start_line_512b.circom b/builds/target_512b/http_parse_and_lock_start_line_512b.circom new file mode 100644 index 0000000..92c2bc8 --- /dev/null +++ b/builds/target_512b/http_parse_and_lock_start_line_512b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/http/nivc/parse_and_lock_start_line.circom"; + +component main { public [step_in] } = ParseAndLockStartLine(512, 10, 20, 20, 20); \ No newline at end of file diff --git a/builds/target_512b/json_extract_value_512b.circom b/builds/target_512b/json_extract_value_512b.circom new file mode 100644 index 0000000..a7fa283 --- /dev/null +++ b/builds/target_512b/json_extract_value_512b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/extractor.circom"; + +component main { public [step_in] } = MaskExtractFinal(512, 10, 50); \ No newline at end of file diff --git a/builds/target_512b/json_mask_array_index_512b.circom b/builds/target_512b/json_mask_array_index_512b.circom new file mode 100644 index 0000000..ec72dc7 --- /dev/null +++ b/builds/target_512b/json_mask_array_index_512b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskArrayIndexNIVC(512, 10); \ No newline at end of file diff --git a/builds/target_512b/json_mask_object_512b.circom b/builds/target_512b/json_mask_object_512b.circom new file mode 100644 index 0000000..3bd0e31 --- /dev/null +++ b/builds/target_512b/json_mask_object_512b.circom @@ -0,0 +1,5 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/masker.circom"; + +component main { public [step_in] } = JsonMaskObjectNIVC(512, 10, 10); diff --git a/builds/target_512b/json_parse_512b.circom b/builds/target_512b/json_parse_512b.circom new file mode 100644 index 0000000..a48a10b --- /dev/null +++ b/builds/target_512b/json_parse_512b.circom @@ -0,0 +1,6 @@ +pragma circom 2.1.9; + +include "../../circuits/json/nivc/parse.circom"; + +component main { public [step_in] } = JsonParseNIVC(512, 10); + From 55f1500537a37142acaeaf2bbcd7db8527cf0e5e Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 4 Nov 2024 15:55:21 +0700 Subject: [PATCH 18/21] change build names for correctness --- .github/workflows/artifacts.yaml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml index 30cda10..a65e3a4 100644 --- a/.github/workflows/artifacts.yaml +++ b/.github/workflows/artifacts.yaml @@ -1,4 +1,4 @@ -name: build-circuits +name: build-artifacts concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7e112e2..56d22ba 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ on: branches: [ main ] jobs: - circom: + test: runs-on: ubuntu-latest steps: From f9a7bc8e23c72ee485e5173f8b08531edb39fa58 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 4 Nov 2024 15:58:45 +0700 Subject: [PATCH 19/21] chore: missed a save on 256 bit size --- builds/target_256b/http_body_mask_256b.circom | 2 +- builds/target_256b/http_lock_header_256b.circom | 2 +- builds/target_256b/http_parse_and_lock_start_line_256b.circom | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/builds/target_256b/http_body_mask_256b.circom b/builds/target_256b/http_body_mask_256b.circom index ffb3b7e..cb65ee5 100644 --- a/builds/target_256b/http_body_mask_256b.circom +++ b/builds/target_256b/http_body_mask_256b.circom @@ -2,5 +2,5 @@ pragma circom 2.1.9; include "../../circuits/http/nivc/body_mask.circom"; -component main { public [step_in] } = HTTPMaskBodyNIVC(512, 10); +component main { public [step_in] } = HTTPMaskBodyNIVC(256, 10); diff --git a/builds/target_256b/http_lock_header_256b.circom b/builds/target_256b/http_lock_header_256b.circom index 02d9dc9..892e013 100644 --- a/builds/target_256b/http_lock_header_256b.circom +++ b/builds/target_256b/http_lock_header_256b.circom @@ -2,4 +2,4 @@ pragma circom 2.1.9; include "../../circuits/http/nivc/lock_header.circom"; -component main { public [step_in] } = LockHeader(512, 10, 50, 100); \ No newline at end of file +component main { public [step_in] } = LockHeader(256, 10, 50, 100); \ No newline at end of file diff --git a/builds/target_256b/http_parse_and_lock_start_line_256b.circom b/builds/target_256b/http_parse_and_lock_start_line_256b.circom index 92c2bc8..708f35a 100644 --- a/builds/target_256b/http_parse_and_lock_start_line_256b.circom +++ b/builds/target_256b/http_parse_and_lock_start_line_256b.circom @@ -2,4 +2,4 @@ pragma circom 2.1.9; include "../../circuits/http/nivc/parse_and_lock_start_line.circom"; -component main { public [step_in] } = ParseAndLockStartLine(512, 10, 20, 20, 20); \ No newline at end of file +component main { public [step_in] } = ParseAndLockStartLine(256, 10, 20, 20, 20); \ No newline at end of file From 7abcedc1f8602d347d9192ba9d5f87bea3f4c0b5 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 4 Nov 2024 16:36:29 +0700 Subject: [PATCH 20/21] chore: wit-calc needs protoc --- .github/workflows/test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 56d22ba..6220c6a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,11 @@ jobs: - name: Run tests run: npm run test + - name: Install Protocol Buffers + run: | + sudo apt-get update + sudo apt-get install -y protobuf-compiler libprotobuf-dev + - name: Install circom-witnesscalc run: | cd .. && git clone https://github.com/pluto/circom-witnesscalc.git From 134a1daab1c75a1b7296c41211c491ae31ad77c5 Mon Sep 17 00:00:00 2001 From: Waylon Jepsen Date: Mon, 4 Nov 2024 16:55:34 +0700 Subject: [PATCH 21/21] CI --- .github/workflows/artifacts.yaml | 2 +- .github/workflows/test.yml | 18 +----------------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/artifacts.yaml b/.github/workflows/artifacts.yaml index a65e3a4..dfcafbd 100644 --- a/.github/workflows/artifacts.yaml +++ b/.github/workflows/artifacts.yaml @@ -83,7 +83,7 @@ jobs: run: | make debug # Show what will be processed make build # Build the circuits - + - name: Create release artifacts run: | # Get the list of target directories diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6220c6a..31e0721 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,20 +36,4 @@ jobs: circom --version - name: Run tests - run: npm run test - - - name: Install Protocol Buffers - run: | - sudo apt-get update - sudo apt-get install -y protobuf-compiler libprotobuf-dev - - - name: Install circom-witnesscalc - run: | - cd .. && git clone https://github.com/pluto/circom-witnesscalc.git - cd circom-witnesscalc - cargo install --path . - echo $(which build-circuit) - - - name: Run build-circuit on target files - run: | - build-circuit builds/target_256b/*.circom \ No newline at end of file + run: npm run test \ No newline at end of file