Skip to content

Commit

Permalink
use updated circuits local paths. All compile
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJepsen committed Nov 1, 2024
1 parent 10c9c07 commit cf2b7f2
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 556 deletions.
1 change: 0 additions & 1 deletion circuits/aes-gctr-nivc.circom
Original file line number Diff line number Diff line change
Expand Up @@ -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);
34 changes: 2 additions & 32 deletions circuits/extract_value.circom
Original file line number Diff line number Diff line change
@@ -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<TOTAL_BYTES ; i++) {
is_zero_mask[i] <== IsZero()(step_in[i]);
is_prev_starting_index[i] <== IsZero()(value_starting_index[i-1]);
value_starting_index[i] <== value_starting_index[i-1] + i * (1-is_zero_mask[i]) * is_prev_starting_index[i];
}

// log("value starting index", value_starting_index[TOTAL_BYTES-1]);

signal value[maxValueLen] <== SelectSubArray(TOTAL_BYTES, maxValueLen)(step_in, value_starting_index[TOTAL_BYTES-1], maxValueLen);
for (var i = 0 ; i < maxValueLen ; i++) {
// log(i, value[i]);
step_out[i] <== value[i];
}
for (var i = maxValueLen ; i < TOTAL_BYTES ; i++) {
step_out[i] <== 0;
}
}

component main { public [step_in] } = MaskExtractFinal(4160, 200);
component main { public [step_in] } = MaskExtractFinal(49, 32, 32);
34 changes: 1 addition & 33 deletions circuits/http_body_mask.circom
Original file line number Diff line number Diff line change
@@ -1,38 +1,6 @@
pragma circom 2.1.9;

include "parser-attestor/circuits/http/interpreter.circom";

template HTTPMaskBodyNIVC(TOTAL_BYTES, DATA_BYTES) {
// ------------------------------------------------------------------------------------------------------------------ //
// ~~ 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 = 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);

86 changes: 3 additions & 83 deletions circuits/http_lock_header.circom
Original file line number Diff line number Diff line change
@@ -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

125 changes: 2 additions & 123 deletions circuits/http_parse_and_lock_start_line.circom
Original file line number Diff line number Diff line change
@@ -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);
component main { public [step_in] } = ParseAndLockStartLine(48, 16, 8, 3, 2);
4 changes: 1 addition & 3 deletions circuits/json/nivc/extractor.circom
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
70 changes: 2 additions & 68 deletions circuits/json_mask_array_index.circom
Original file line number Diff line number Diff line change
@@ -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);
component main { public [step_in] } = JsonMaskArrayIndexNIVC(48, 16);
Loading

0 comments on commit cf2b7f2

Please sign in to comment.