Skip to content

Commit

Permalink
feat byte packing
Browse files Browse the repository at this point in the history
  • Loading branch information
Autoparallel committed Nov 6, 2024
1 parent e2e855a commit 7228137
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 20 deletions.
5 changes: 1 addition & 4 deletions circuits/aes-gcm/nivc/aes-gctr-nivc.circom
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ template AESGCTRFOLD(DATA_BYTES) {
}

// Write out the plaintext and ciphertext to our accumulation arrays, both at once.
signal nextPackedChunk[16];
for(var i = 0 ; i < 16 ; i++) {
nextPackedChunk[i] <== plainText[i] + 2**8 * aes.cipherText[i];
}
signal nextPackedChunk[16] <== DoubleBytePackArray(16)(plainText, aes.cipherText);

signal prevAccumulatedPackedText[DATA_BYTES];
for(var i = 0 ; i < DATA_BYTES ; i++) {
Expand Down
2 changes: 1 addition & 1 deletion circuits/http/nivc/body_mask.circom
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include "../parser/machine.circom";

template HTTPMaskBodyNIVC(DATA_BYTES) {
// ------------------------------------------------------------------------------------------------------------------ //
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // aes ct/pt + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr
// ------------------------------------------------------------------------------------------------------------------ //

// ------------------------------------------------------------------------------------------------------------------ //
Expand Down
2 changes: 1 addition & 1 deletion circuits/http/nivc/lock_header.circom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ include "circomlib/circuits/comparators.circom";
// TODO: should use a MAX_HEADER_NAME_LENGTH and a MAX_HEADER_VALUE_LENGTH
template LockHeader(DATA_BYTES, MAX_HEADER_NAME_LENGTH, MAX_HEADER_VALUE_LENGTH) {
// ------------------------------------------------------------------------------------------------------------------ //
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // aes pt/ct + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes pt/ct + ctr
// ------------------------------------------------------------------------------------------------------------------ //

// ------------------------------------------------------------------------------------------------------------------ //
Expand Down
11 changes: 7 additions & 4 deletions circuits/http/nivc/parse_and_lock_start_line.circom
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ include "../../utils/bytes.circom";
template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENGTH, MAX_FINAL_LENGTH) {
// ------------------------------------------------------------------------------------------------------------------ //
// ~~ Set sizes at compile time ~~
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // AES ct/pt + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // AES ct/pt + ctr
// ------------------------------------------------------------------------------------------------------------------ //

// ------------------------------------------------------------------------------------------------------------------ //
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];

// Get the plaintext
signal data[DATA_BYTES];
signal packedData[DATA_BYTES];
for (var i = 0 ; i < DATA_BYTES ; i++) {
data[i] <== step_in[i];
packedData[i] <== step_in[i];
}
component unpackData = UnpackDoubleByteArray(DATA_BYTES);
unpackData.in <== packedData;
signal data[DATA_BYTES] <== unpackData.lower;

signal input beginning[MAX_BEGINNING_LENGTH];
signal input beginning_length;
Expand Down Expand Up @@ -100,7 +103,7 @@ template ParseAndLockStartLine(DATA_BYTES, MAX_BEGINNING_LENGTH, MAX_MIDDLE_LENG
for (var i = 0 ; i < TOTAL_BYTES_ACROSS_NIVC ; i++) {
// add plaintext http input to step_out and ignore the ciphertext
if(i < DATA_BYTES) {
step_out[i] <== step_in[i];
step_out[i] <== data[i]; // PASS OUT JUST THE PLAINTEXT DATA
} else {
step_out[i] <== 0;
}
Expand Down
2 changes: 1 addition & 1 deletion circuits/json/nivc/extractor.circom
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include "@zk-email/circuits/utils/array.circom";

template MaskExtractFinal(DATA_BYTES, MAX_VALUE_LENGTH) {
// ------------------------------------------------------------------------------------------------------------------ //
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // aes pt/ct + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes pt/ct + ctr
// ------------------------------------------------------------------------------------------------------------------ //
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];
Expand Down
8 changes: 4 additions & 4 deletions circuits/json/nivc/masker.circom
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include "../interpreter.circom";
template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
// ------------------------------------------------------------------------------------------------------------------ //
assert(MAX_STACK_HEIGHT >= 2); // TODO (autoparallel): idk if we need this now
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // aes ct/pt + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr
// ------------------------------------------------------------------------------------------------------------------ //
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];
Expand Down Expand Up @@ -87,15 +87,15 @@ template JsonMaskObjectNIVC(DATA_BYTES, MAX_STACK_HEIGHT, MAX_KEY_LENGTH) {
// mask = currently parsing value and all subsequent keys matched
step_out[data_idx] <== data[data_idx] * or[data_idx - 1];
}
for(var i = DATA_BYTES - MAX_KEY_LENGTH; i < 2 * DATA_BYTES + 4; i ++) {
for(var i = DATA_BYTES - MAX_KEY_LENGTH; i < DATA_BYTES + 4; i ++) {
step_out[i] <== 0;
}
}

template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
// ------------------------------------------------------------------------------------------------------------------ //
assert(MAX_STACK_HEIGHT >= 2); // TODO (autoparallel): idk if we need this now
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4; // aes ct/pt + ctr
var TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4; // aes ct/pt + ctr
// ------------------------------------------------------------------------------------------------------------------ //
signal input step_in[TOTAL_BYTES_ACROSS_NIVC];
signal output step_out[TOTAL_BYTES_ACROSS_NIVC];
Expand Down Expand Up @@ -136,7 +136,7 @@ template JsonMaskArrayIndexNIVC(DATA_BYTES, MAX_STACK_HEIGHT) {
or[data_idx - 1] <== OR()(parsing_array[data_idx], parsing_array[data_idx - 1]);
step_out[data_idx] <== data[data_idx] * or[data_idx - 1];
}
for(var i = DATA_BYTES ; i < 2 * DATA_BYTES + 4; i++) {
for(var i = DATA_BYTES ; i < TOTAL_BYTES_ACROSS_NIVC; i++) {
step_out[i] <== 0;
}
}
6 changes: 2 additions & 4 deletions circuits/test/full/full.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe("NIVC_FULL", async () => {

const DATA_BYTES = 320;
const MAX_STACK_HEIGHT = 5;
const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES * 2 + 4;
const TOTAL_BYTES_ACROSS_NIVC = DATA_BYTES + 4;

const MAX_HEADER_NAME_LENGTH = 20;
const MAX_HEADER_VALUE_LENGTH = 35;
Expand Down Expand Up @@ -132,7 +132,7 @@ describe("NIVC_FULL", async () => {
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;
init_nivc_input[DATA_BYTES + index] = value;
});
let pt = http_response_plaintext.slice(0, 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"]);
Expand All @@ -154,8 +154,6 @@ describe("NIVC_FULL", async () => {
let maskedInput = extendedJsonInput.fill(0, 0, idx);
maskedInput = maskedInput.fill(0, 320);



let key0 = [100, 97, 116, 97, 0, 0, 0, 0]; // "data"
let key0Len = 4;
let key1 = [105, 116, 101, 109, 115, 0, 0, 0]; // "items"
Expand Down
96 changes: 96 additions & 0 deletions circuits/test/utils/bytes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,100 @@ describe("ASCII", () => {
{ in: [256, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] }
);
});
});

describe("BytePack", () => {
let circuit: WitnessTester<["lower", "upper"], ["out"]>;
before(async () => {
circuit = await circomkit.WitnessTester(`DoubleBytePackArray`, {
file: "utils/bytes",
template: "DoubleBytePackArray",
params: [1],
});
console.log("#constraints:", await circuit.getConstraintCount());
});

it("witness: lower = 0, upper = 1", async () => {
await circuit.expectPass(
{ lower: [0], upper: [1] }, { out: [256] }
);
});

it("witness: lower = 1, upper = 1", async () => {
await circuit.expectPass(
{ lower: [1], upper: [1] }, { out: [257] }
);
});

it("witness: lower = 1, upper = 0", async () => {
await circuit.expectPass(
{ lower: [1], upper: [0] }, { out: [1] }
);
});
});

describe("BytePack2", () => {
let circuit: WitnessTester<["lower", "upper"], ["out"]>;
before(async () => {
circuit = await circomkit.WitnessTester(`DoubleBytePackArray`, {
file: "utils/bytes",
template: "DoubleBytePackArray",
params: [2],
});
console.log("#constraints:", await circuit.getConstraintCount());
});
it("witness: lower = [1,0], upper = [0,1]", async () => {
await circuit.expectPass(
{ lower: [1, 0], upper: [0, 1] }, { out: [1, 256] }
);
});
});

describe("ByteUnpack", () => {
let circuit: WitnessTester<["in"], ["lower", "upper"]>;
before(async () => {
circuit = await circomkit.WitnessTester(`UnpackDoubleByteArray`, {
file: "utils/bytes",
template: "UnpackDoubleByteArray",
params: [1],
});
console.log("#constraints:", await circuit.getConstraintCount());
});

it("witness: in = 256", async () => {
await circuit.expectPass(
{ in: [256] }, { lower: [0], upper: [1] }
);
});

it("witness: in = 257", async () => {
await circuit.expectPass(
{ in: [257] }, { lower: [1], upper: [1] }
);
});

it("witness: in = 1", async () => {
await circuit.expectPass(
{ in: [1] }, { lower: [1], upper: [] }
);
});
});

describe("ByteUnpack2", () => {
let circuit: WitnessTester<["in"], ["lower", "upper"]>;
before(async () => {
circuit = await circomkit.WitnessTester(`UnpackDoubleByteArray`, {
file: "utils/bytes",
template: "UnpackDoubleByteArray",
params: [2],
});
console.log("#constraints:", await circuit.getConstraintCount());
});

it("witness: in = [1,256]", async () => {
await circuit.expectPass(
{ in: [1, 256] }, { lower: [1, 0], upper: [0, 1] }
);
});

});
26 changes: 25 additions & 1 deletion circuits/utils/bytes.circom
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,31 @@ template DoubleBytePackArray(n) {
signal input upper[n];
signal output out[n];

for(var i = 0 ; i < 16 ; i++) {
for(var i = 0 ; i < n ; i++) {
out[i] <== lower[i] + 2**8 * upper[i];
}
}

template UnpackDoubleByteArray(n) {
signal input in[n];
signal output lower[n];
signal output upper[n];

signal inBits[n][16];
var lowerAccum[n];
var upperAccum[n];
for(var i = 0 ; i < n ; i ++) {
inBits[i] <== Num2Bits(16)(in[i]);
lowerAccum[i] = 0;
upperAccum[i] = 0;
for(var j = 0 ; j < 16 ; j++) {
if(j < 8) {
lowerAccum[i] += inBits[i][j] * 2**j;
} else {
upperAccum[i] += inBits[i][j] * 2**(j-8);
}
}
}
lower <== lowerAccum;
upper <== upperAccum;
}

0 comments on commit 7228137

Please sign in to comment.