Skip to content

Commit

Permalink
cleanup: unused signals, consistency
Browse files Browse the repository at this point in the history
Found unused signals with the circom-witnesscalc `build-circuit` binary. These are now removed.
  • Loading branch information
Autoparallel committed Oct 20, 2024
1 parent 0962990 commit 57b0542
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 71 deletions.
85 changes: 18 additions & 67 deletions circuits/json/nivc/masker.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pragma circom 2.1.9;

include "../interpreter.circom";
include "../../utils/array.circom";

template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
// ------------------------------------------------------------------------------------------------------------------ //
Expand All @@ -15,14 +16,15 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
// ~ Unravel from previous NIVC step ~
// Read in from previous NIVC step (JsonParseNIVC)
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];

// Grab the raw data bytes from the `step_in` variable
var paddedDataLen = DATA_BYTES + MAX_KEY_LENGTH + 1;
signal data[paddedDataLen];
for (var i = 0 ; i < DATA_BYTES ; i++) {
data[i] <== step_in[i];
}
for (var i = 0 ; i <= MAX_KEY_LENGTH ; i++) {
for (var i = 0 ; i < MAX_KEY_LENGTH + 1 ; i++) {
data[DATA_BYTES + i] <== 0;
}

Expand All @@ -35,8 +37,8 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
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];
} else {
// TODO: Now need to do "if curr_depth == MAX_STACK_HEIGHT", set nextStackSelector <== [0,0]
// Add one extra stack element without doing this while parsing.
// Stack under/overflow caught in parsing.
stack[i][j][0] <== 0;
stack[i][j][1] <== 0;
}
Expand Down Expand Up @@ -84,10 +86,10 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
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];

signal output step_out[TOTAL_BYTES_ACROSS_NIVC];
step_out[0] <== data[0] * is_value_match[0];

signal or[DATA_BYTES];
or[0] <== is_value_match[0];
step_out[0] <== data[0] * or[0];

for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) {
// Grab the stack at the indicated height (from `step_in`)
stackSelector[data_idx] = ArraySelector(MAX_STACK_HEIGHT + 1, 2);
Expand All @@ -98,33 +100,23 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
nextStackSelector[data_idx].in <== stack[data_idx];
nextStackSelector[data_idx].index <== step_in[TOTAL_BYTES_ACROSS_NIVC - 1] + 1;

// log("stackSelector[", data_idx, "].out[0] = ", stackSelector[data_idx].out[0]);
// log("stackSelector[", data_idx, "].out[1] = ", stackSelector[data_idx].out[1]);

// Detect if we are parsing
parsing_key[data_idx] <== InsideKey()(stackSelector[data_idx].out, parsingData[data_idx][0], parsingData[data_idx][1]);
parsing_value[data_idx] <== InsideValueObject()(stackSelector[data_idx].out, nextStackSelector[data_idx].out, parsingData[data_idx][0], parsingData[data_idx][1]);

// log("parsing_key[", data_idx, "] = ", parsing_key[data_idx]);
// log("parsing_value[", data_idx, "] = ", parsing_value[data_idx]);

// 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(paddedDataLen, MAX_KEY_LENGTH, data_idx)(data, key, keyLen, parsing_key[data_idx]);
is_next_pair_at_depth[data_idx] <== NextKVPairAtDepth(MAX_STACK_HEIGHT + 1)(stack[data_idx], data[data_idx], step_in[TOTAL_BYTES_ACROSS_NIVC - 1]);

// log("is_key_match[", data_idx, "] = ", is_key_match[data_idx]);
// log("is_next_pair_at_depth[", data_idx, "] = ", is_next_pair_at_depth[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];

// Set the next NIVC step to only have the masked data
or[data_idx] <== OR()(is_value_match[data_idx], is_value_match[data_idx -1]);
or[data_idx] <== OR()(is_value_match[data_idx], is_value_match[data_idx -1]);
step_out[data_idx] <== data[data_idx] * or[data_idx];
// log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
// Append the parser state back on `step_out`
for (var i = DATA_BYTES ; i < TOTAL_BYTES_ACROSS_NIVC - 1 ; i++) {
Expand All @@ -148,7 +140,8 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
// ------------------------------------------------------------------------------------------------------------------ //
// ~ Unravel from previous NIVC step ~
// Read in from previous NIVC step (JsonParseNIVC)
signal input step_in[TOTAL_BYTES_ACROSS_NIVC]; // ADD 1 FOR CURRENT STACK POINTER
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];

// Grab the raw data bytes from the `step_in` variable
signal data[DATA_BYTES];
Expand All @@ -165,8 +158,8 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
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];
} else {
// TODO: Now need to do "if curr_depth == MAX_STACK_HEIGHT", set nextStackSelector <== [0,0]
// Add one extra stack element without doing this while parsing.
// Stack under/overflow caught in parsing.
stack[i][j][0] <== 0;
stack[i][j][1] <== 0;
}
Expand All @@ -181,12 +174,7 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
// ~ 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]; // Maybe don't need
signal parsing_array[DATA_BYTES];

component stackSelector[DATA_BYTES];
stackSelector[0] = ArraySelector(MAX_STACK_HEIGHT + 1, 2);
Expand All @@ -199,8 +187,10 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
nextStackSelector[0].index <== step_in[TOTAL_BYTES_ACROSS_NIVC - 1] + 1;

parsing_array[0] <== InsideArrayIndexObject()(stackSelector[0].out, nextStackSelector[0].out, parsingData[0][0], parsingData[0][1], index);
mask[0] <== data[0] * parsing_array[0];

signal or[DATA_BYTES];
or[0] <== parsing_array[0];
step_out[0] <== data[0] * or[0];
for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) {
stackSelector[data_idx] = ArraySelector(MAX_STACK_HEIGHT + 1, 2);
stackSelector[data_idx].in <== stack[data_idx];
Expand All @@ -210,57 +200,18 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
nextStackSelector[data_idx].in <== stack[data_idx];
nextStackSelector[data_idx].index <== step_in[TOTAL_BYTES_ACROSS_NIVC - 1] + 1;

// log("stackSelector[", data_idx, "].out[0] = ", stackSelector[data_idx].out[0]);
// log("stackSelector[", data_idx, "].out[1] = ", stackSelector[data_idx].out[1]);
// log("nextStackSelector[", data_idx, "].out[0] = ", nextStackSelector[data_idx].out[0]);
// log("nextStackSelector[", data_idx, "].out[1] = ", nextStackSelector[data_idx].out[1]);

parsing_array[data_idx] <== InsideArrayIndexObject()(stackSelector[data_idx].out, nextStackSelector[data_idx].out, 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];
or[data_idx] <== OR()(parsing_array[data_idx], parsing_array[data_idx - 1]);
step_out[data_idx] <== data[data_idx] * or[data_idx];
}

// Write the `step_out` with masked data
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];
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_ACROSS_NIVC - 1 ; i++) {
step_out[i] <== step_in[i];
}
// No need to pad as this is currently when TOTAL_BYTES == TOTAL_BYTES_USED
step_out[TOTAL_BYTES_ACROSS_NIVC - 1] <== step_in[TOTAL_BYTES_ACROSS_NIVC - 1] + 1;
}

template ArraySelector(m, n) {
signal input in[m][n];
signal input index;
signal output out[n];
assert(index >= 0 && index < m);

signal selector[m];
component Equal[m];
for (var i = 0; i < m; i++) {
selector[i] <== IsEqual()([index, i]);
}

var sum = 0;
for (var i = 0; i < m; i++) {
sum += selector[i];
}
sum === 1;

signal sums[n][m+1];
// note: loop order is column-wise, not row-wise
for (var j = 0; j < n; j++) {
sums[j][0] <== 0;
for (var i = 0; i < m; i++) {
sums[j][i+1] <== sums[j][i] + in[i][j] * selector[i];
}
out[j] <== sums[j][m];
}
}

// component main { public [step_in] } = JsonMaskObjectNIVC(320, 5, 7);
5 changes: 1 addition & 4 deletions circuits/test/json/nivc/masker_nivc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ describe("JsonMaskObjectNIVC", async () => {

it(`(valid) witness: ${desc}`, async () => {
// console.log(JSON.stringify(await circuit.compute(input, ["step_out"])))
let wit = await circuit.calculateWitness(input);
// console.log("wit", wit.slice(0, 100));
// step_out = wit;
await circuit.expectPass(input, expected);
});
}
Expand Down Expand Up @@ -178,7 +175,7 @@ describe("JsonExtractNIVC", async () => {
const description = generateDescription(input);

it(`(valid) witness: ${desc}`, async () => {
console.log(JSON.stringify(await circuit.compute(input, ["step_out", "value"])))
// console.log(JSON.stringify(await circuit.compute(input, ["step_out", "value"])))
await circuit.expectPass(input, expected);
});
}
Expand Down
31 changes: 31 additions & 0 deletions circuits/utils/array.circom
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ template ScalarArrayMul(n) {
}
}

// TODO: Below really needs documentation.

// from: https://github.com/pluto/aes-proof/blob/main/circuits/aes-gcm/helper_functions.circom
template SumMultiple(n) {
signal input nums[n];
Expand Down Expand Up @@ -229,4 +231,33 @@ template IndexSelector(total) {
}

out <== calcTotal.sum;
}

template ArraySelector(m, n) {
signal input in[m][n];
signal input index;
signal output out[n];
assert(index >= 0 && index < m);

signal selector[m];
component Equal[m];
for (var i = 0; i < m; i++) {
selector[i] <== IsEqual()([index, i]);
}

var sum = 0;
for (var i = 0; i < m; i++) {
sum += selector[i];
}
sum === 1;

signal sums[n][m+1];
// note: loop order is column-wise, not row-wise
for (var j = 0; j < n; j++) {
sums[j][0] <== 0;
for (var i = 0; i < m; i++) {
sums[j][i+1] <== sums[j][i] + in[i][j] * selector[i];
}
out[j] <== sums[j][m];
}
}

0 comments on commit 57b0542

Please sign in to comment.