diff --git a/circuits/test/http/codegen.test.ts b/circuits/test/http/codegen.test.ts index 9a872f2..1d08884 100644 --- a/circuits/test/http/codegen.test.ts +++ b/circuits/test/http/codegen.test.ts @@ -78,7 +78,7 @@ describe("HTTP :: Codegen :: Request", async () => { const lockData = await readLockFile(`${lockfile}.json`); console.log("lockData: ", JSON.stringify(lockData)); - const input = await readHTTPInputFile(`${inputfile}`).input + const input = await readHTTPInputFile(`${inputfile}`).input; const headers = getHeaders(lockData); const params = [input.length, lockData.method.length, lockData.target.length, lockData.version.length]; @@ -154,7 +154,7 @@ describe("HTTP :: Codegen :: Request", async () => { }); describe("HTTP :: Codegen :: Response", async () => { - let circuit: WitnessTester<["data", "version", "status", "message", "header1", "value1", "header2", "value2"], []>; + let circuit: WitnessTester<["data", "version", "status", "message", "header1", "value1", "header2", "value2"], ["body"]>; it("(valid) GET:", async () => { let lockfile = "response.lock"; @@ -166,10 +166,12 @@ describe("HTTP :: Codegen :: Response", async () => { const lockData = await readLockFile(`${lockfile}.json`); console.log("lockData: ", JSON.stringify(lockData)); - const input = await readHTTPInputFile(`${inputfile}`).input + const http = await readHTTPInputFile(`${inputfile}`); + const input = http.input; const headers = getHeaders(lockData); - const params = [input.length, lockData.version.length, lockData.status.length, lockData.message.length]; + + const params = [input.length, parseInt(http.headers["Content-Length"]), lockData.version.length, lockData.status.length, lockData.message.length]; headers.forEach(header => { params.push(header[0].length); params.push(header[1].length); @@ -195,7 +197,9 @@ describe("HTTP :: Codegen :: Response", async () => { circuitInput[`header${index + 1}`] = toByte(header[0]); circuitInput[`value${index + 1}`] = toByte(header[1]); }); - await circuit.expectPass(circuitInput, {}); + + + await circuit.expectPass(circuitInput, { body: http.bodyBytes }); }); it("(invalid) GET:", async () => { @@ -207,10 +211,12 @@ describe("HTTP :: Codegen :: Response", async () => { const lockData = await readLockFile(`${lockfile}.json`); - const input = await readHTTPInputFile(`${inputfile}`).input + const http = await readHTTPInputFile(`${inputfile}`); + const input = http.input; const headers = getHeaders(lockData); - const params = [input.length, lockData.version.length, lockData.status.length, lockData.message.length]; + + const params = [input.length, parseInt(http.headers["Content-Length"]), lockData.version.length, lockData.status.length, lockData.message.length]; headers.forEach(header => { params.push(header[0].length); params.push(header[1].length); diff --git a/src/http.rs b/src/http.rs index 5470446..f0cbb65 100644 --- a/src/http.rs +++ b/src/http.rs @@ -99,7 +99,7 @@ fn build_http_circuit( } HttpData::Response(_) => { circuit_buffer += - "template LockHTTPResponse(DATA_BYTES, versionLen, statusLen, messageLen"; + "template LockHTTPResponse(DATA_BYTES, maxContentLength, versionLen, statusLen, messageLen"; } } @@ -155,6 +155,19 @@ fn build_http_circuit( } } + // Create an output if circuit is for `Response` + { + if let HttpData::Response(_) = data { + circuit_buffer += r#" + // Set up mask bits for where the body of response lies + signal output body[maxContentLength]; + + signal bodyMask[DATA_BYTES]; + bodyMask[0] <== 0; +"#; + } + } + // Setup for parsing the start line { match data { @@ -233,6 +246,16 @@ fn build_http_circuit( "#; } + // If parsing a `Response`, create a mask of the body bytes + { + if let HttpData::Response(_) = data { + circuit_buffer += r#" + // Mask if parser is in the body of response + bodyMask[data_idx] <== data[data_idx] * State[data_idx].next_parsing_body; +"#; + } + } + // Start line matches { match data { @@ -320,6 +343,34 @@ fn build_http_circuit( "#; } + // Get the output body bytes + { + if let HttpData::Response(_) = data { + circuit_buffer += r#" + signal bodyStartingIndex[DATA_BYTES]; + signal isZeroMask[DATA_BYTES]; + signal isPrevStartingIndex[DATA_BYTES]; + bodyStartingIndex[0] <== 0; + isZeroMask[0] <== IsZero()(bodyMask[0]); + for (var i=1 ; i < DATA_BYTES; i++) { + isZeroMask[i] <== IsZero()(bodyMask[i]); + isPrevStartingIndex[i] <== IsZero()(bodyStartingIndex[i-1]); + bodyStartingIndex[i] <== bodyStartingIndex[i-1] + i * (1-isZeroMask[i]) * isPrevStartingIndex[i]; + } + + body <== SelectSubArray(DATA_BYTES, maxContentLength)(bodyMask, bodyStartingIndex[DATA_BYTES-1]+1, DATA_BYTES - bodyStartingIndex[DATA_BYTES-1]); +"#; + } + } + + if debug { + circuit_buffer += r#" + for(var i = 0; i < maxContentLength; i++) { + log("body[", i, "] = ", body[i]); + } +"#; + } + // Verify all start line has matched { match data {