Skip to content

Commit

Permalink
resetting for clearer approach
Browse files Browse the repository at this point in the history
  • Loading branch information
Autoparallel committed Nov 15, 2024
1 parent cb44e39 commit 01691f4
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 115 deletions.
146 changes: 80 additions & 66 deletions circuits/json/parser/hash_machine.circom
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ template StateUpdateHasher(MAX_STACK_HEIGHT) {
signal input stack[MAX_STACK_HEIGHT][2];
signal input parsing_string;
signal input parsing_number;
signal input tree_hasher[MAX_STACK_HEIGHT];
signal input tree_hasher[MAX_STACK_HEIGHT][2];

signal output next_stack[MAX_STACK_HEIGHT][2];
signal output next_parsing_string;
signal output next_parsing_number;
signal output next_tree_hasher[MAX_STACK_HEIGHT];
signal output next_tree_hasher[MAX_STACK_HEIGHT][2];

component Command = Command();

Expand Down Expand Up @@ -144,6 +144,8 @@ template StateUpdateHasher(MAX_STACK_HEIGHT) {
signal current_value[2] <== topOfStack.value;
component newStack = RewriteStack(MAX_STACK_HEIGHT);
newStack.stack <== stack;
newStack.tree_hasher <== tree_hasher;
newStack.byte <== byte;
newStack.pointer <== pointer;
newStack.current_value <== current_value;
newStack.read_write_value <== mulMaskAndOut.out[0];
Expand All @@ -157,74 +159,74 @@ template StateUpdateHasher(MAX_STACK_HEIGHT) {
next_stack <== newStack.next_stack;
next_parsing_string <== parsing_string + mulMaskAndOut.out[1];
next_parsing_number <== parsing_number + mulMaskAndOut.out[2];
signal next_pointer <== newStack.next_pointer;
next_tree_hasher <== newStack.next_tree_hasher;
//--------------------------------------------------------------------------------------------//

//--------------------------------------------------------------------------------------------//
// Get the next tree hasher state
/*
Idea:
We basically want a hasher that only hashes the KVs in a tree structure, so we have it
store a hash array for the KV hash at a given depth. We will have to accumulate bytes
into the hasher state while reading a value, so ultimately we want to check the hash array
pointer changes right after we get a hash match on the key byte sequence.
To start, let's just get something that hashes into the array like a buffer.
*/
// Get the next state hash
component packedState = GenericBytePackArray(4,1);
packedState.in <== [ [byte], [pointer], [current_value[0]], [current_value[1]] ];
signal state_hash <== IndexSelector(MAX_STACK_HEIGHT)(tree_hasher, pointer - 1);
signal next_state_hash <== PoseidonChainer()([state_hash, packedState.out[0]]);

// TODO: can probably output these from rewrite stack
// Now, use this to know how to modify the tree_hasher
signal is_push <== IsZero()(next_pointer - (pointer + 1));
signal is_pop <== IsZero()(next_pointer - (pointer - 1));


// signal was_write <== parsing_number + parsing_string; // only write to slot if we are parsing a value type
// signal is_next_write <== next_parsing_number + next_parsing_string; // only write to slot if we are parsing a value type
// signal is_write <== was_write * is_next_write;

signal was_and_is_parsing_string <== parsing_string * next_parsing_string;
signal is_write <== was_and_is_parsing_string + next_parsing_number;

// signal what_to_write <== is_write * next_state_hash;
// signal where_to_write_at[MAX_STACK_HEIGHT];
// signal what_to_write_at[MAX_STACK_HEIGHT];
// for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++) {
// what_to_write_at[i] <== what_to_write
// }

// for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++) {
// next_tree_hasher[i] <== tree_hasher[i] * (1 - is_pop) + what_to_write_at[i]; // Rewrite the array, replacing at `i`
// }
// //--------------------------------------------------------------------------------------------//
// // Get the next tree hasher state
// /*
// Idea:
// We basically want a hasher that only hashes the KVs in a tree structure, so we have it
// store a hash array for the KV hash at a given depth. We will have to accumulate bytes
// into the hasher state while reading a value, so ultimately we want to check the hash array
// pointer changes right after we get a hash match on the key byte sequence.

// To start, let's just get something that hashes into the array like a buffer.
// */
// // Get the next state hash
// component packedState = GenericBytePackArray(4,1);
// packedState.in <== [ [byte], [pointer], [current_value[0]], [current_value[1]] ];
// signal state_hash <== IndexSelector(MAX_STACK_HEIGHT)(tree_hasher, pointer - 1);
// signal next_state_hash <== PoseidonChainer()([state_hash, packedState.out[0]]);

// // TODO: can probably output these from rewrite stack
// // Now, use this to know how to modify the tree_hasher
// signal is_push <== IsZero()(next_pointer - (pointer + 1));
// signal is_pop <== IsZero()(next_pointer - (pointer - 1));


// // signal was_write <== parsing_number + parsing_string; // only write to slot if we are parsing a value type
// // signal is_next_write <== next_parsing_number + next_parsing_string; // only write to slot if we are parsing a value type
// // signal is_write <== was_write * is_next_write;

// signal was_and_is_parsing_string <== parsing_string * next_parsing_string;
// signal is_write <== was_and_is_parsing_string + next_parsing_number;

// // signal what_to_write <== is_write * next_state_hash;
// // signal where_to_write_at[MAX_STACK_HEIGHT];
// // signal what_to_write_at[MAX_STACK_HEIGHT];
// // for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++) {
// // what_to_write_at[i] <== what_to_write
// // }

// // for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++) {
// // next_tree_hasher[i] <== tree_hasher[i] * (1 - is_pop) + what_to_write_at[i]; // Rewrite the array, replacing at `i`
// // }

signal stack_hashes[MAX_STACK_HEIGHT];
for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++){
stack_hashes[i] <== PoseidonChainer()(next_stack[i]);
}
// signal base_hashes[MAX_STACK_HEIGHT] <== ArrayAdd(MAX_STACK_HEIGHT)(stack_hashes, tree_hasher);
component writeTo = WriteToIndex(MAX_STACK_HEIGHT, 1);
writeTo.array_to_write_to <== stack_hashes;
/*
IDEA:
if push, we write `[state_hash, 0]` at pointer
if pop, we write `[0,0]` at pointer
if neither, we write `[next_state_hash IF is_write ELSE 0, 0 ]
*/
// signal stack_hashes[MAX_STACK_HEIGHT];
// for(var i = 0 ; i < MAX_STACK_HEIGHT ; i++){
// stack_hashes[i] <== PoseidonChainer()(next_stack[i]);
// }
// // signal base_hashes[MAX_STACK_HEIGHT] <== ArrayAdd(MAX_STACK_HEIGHT)(stack_hashes, tree_hasher);
// component writeTo = WriteToIndex(MAX_STACK_HEIGHT, 1);
// writeTo.array_to_write_to <== stack_hashes;
// /*
// IDEA:
// if push, we write `[state_hash, 0]` at pointer
// if pop, we write `[0,0]` at pointer
// if neither, we write `[next_state_hash IF is_write ELSE 0, 0 ]

// */

signal to_write_if_is_write <== next_state_hash * is_write;
signal to_write_if_is_push <== state_hash * is_push;
writeTo.array_to_write_at_index <== [to_write_if_is_write + to_write_if_is_push];
writeTo.index <== next_pointer;
next_tree_hasher <== writeTo.out;
// signal to_write_if_is_write <== next_state_hash * is_write;
// signal to_write_if_is_push <== state_hash * is_push;
// writeTo.array_to_write_at_index <== [to_write_if_is_write + to_write_if_is_push];
// writeTo.index <== next_pointer;
// next_tree_hasher <== writeTo.out;
log("--------------------------------");
log("state_hash: ", state_hash);
log("pointer: ", pointer);
log("next_pointer: ", next_pointer);
// log("state_hash: ", state_hash);
// log("pointer: ", pointer);
// log("next_pointer: ", next_pointer);
log("byte: ", byte);
log("--------------------------------");
}
Expand Down Expand Up @@ -344,9 +346,12 @@ This template is for updating the stack given the current stack and the byte we
template RewriteStack(n) {
assert(n < 2**8);
signal input stack[n][2];
signal input tree_hasher[n][2];
signal input pointer;
signal input current_value[2];

signal input byte;

signal input read_write_value;
signal input readStartBrace;
signal input readStartBracket;
Expand All @@ -356,7 +361,7 @@ template RewriteStack(n) {
signal input readComma;

signal output next_stack[n][2];
signal output next_tree_hasher[n][2]
signal output next_tree_hasher[n][2];

//--------------------------------------------------------------------------------------------//
// * scan value on top of stack *
Expand Down Expand Up @@ -392,6 +397,12 @@ template RewriteStack(n) {
}
//--------------------------------------------------------------------------------------------//

/* TODO: Okay, for sake of simplicity, it would probably be much easier to just use the
WriteToIndex here for both the stack and tree hasher. Much more ergonomic and can probably
replace a good amount of this.
*/


//--------------------------------------------------------------------------------------------//
// * loop to modify the stack by rebuilding it *
signal stack_change_value[2] <== [(isPush.out + isPop.out) * read_write_value, readColon + readCommaInArray - readCommaNotInArray];
Expand All @@ -400,6 +411,9 @@ template RewriteStack(n) {
next_stack[i][0] <== stack[i][0] + indicator[i].out * stack_change_value[0];
second_index_clear[i] <== stack[i][1] * (readEndBrace + readEndBracket); // Checking if we read some end char
next_stack[i][1] <== stack[i][1] + indicator[i].out * (stack_change_value[1] - second_index_clear[i]);

next_tree_hasher[i][0] <== tree_hasher[i][0] + indicator[i].out * (stack_change_value[0] + byte);
next_tree_hasher[i][1] <== tree_hasher[i][1] + indicator[i].out;
}
//--------------------------------------------------------------------------------------------//

Expand Down
26 changes: 7 additions & 19 deletions circuits/json/parser/hash_parser.circom
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,26 @@ include "hash_machine.circom";
template ParserHasher(DATA_BYTES, MAX_STACK_HEIGHT) {
signal input data[DATA_BYTES];

// TODO: Add assertions on the inputs here!

//--------------------------------------------------------------------------------------------//
//-CONSTRAINTS--------------------------------------------------------------------------------//
//--------------------------------------------------------------------------------------------//
component dataASCII = ASCII(DATA_BYTES);
dataASCII.in <== data;
//--------------------------------------------------------------------------------------------//
// Initialze the parser
component State[DATA_BYTES];
State[0] = StateUpdateHasher(MAX_STACK_HEIGHT);
State[0].byte <== data[0];
for(var i = 0; i < MAX_STACK_HEIGHT; i++) {
State[0].stack[i] <== [0,0];
State[0].tree_hasher[i] <== PoseidonChainer()([0,0]);
State[0].stack[i] <== [0,0];
State[0].tree_hasher[i] <== [0,0];
}
State[0].parsing_string <== 0;
State[0].parsing_number <== 0;

// Debugging
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", 0, "].next_stack[", i,"] ", "= [",State[0].next_stack[i][0], "][", State[0].next_stack[i][1],"]" );
log("State[", 0, "].next_stack[", i,"] ", "= [",State[0].next_stack[i][0], "][", State[0].next_stack[i][1],"]" );
log("State[", 0, "].tree_hasher[", i,"] ", "= [",State[0].tree_hasher[i][0], "][", State[0].tree_hasher[i][1],"]" );
}
log("State[", 0, "].next_parsing_string", "= ", State[0].next_parsing_string);
log("State[", 0, "].next_parsing_number", "= ", State[0].next_parsing_number);
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", 0, "].next_tree_hasher[", i,"]", "= ", State[0].next_tree_hasher[i]);
}
log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

for(var data_idx = 1; data_idx < DATA_BYTES; data_idx++) {
Expand All @@ -46,13 +38,11 @@ template ParserHasher(DATA_BYTES, MAX_STACK_HEIGHT) {

// Debugging
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", data_idx, "].stack[", i,"] ", "= [",State[data_idx].next_stack[i][0], "][", State[data_idx].next_stack[i][1],"]" );
log("State[", data_idx, "].next_stack[", i,"] ", "= [",State[data_idx].next_stack[i][0], "][", State[data_idx].next_stack[i][1],"]" );
log("State[", data_idx, "].tree_hasher[", i,"] ", "= [",State[data_idx].tree_hasher[i][0], "][", State[data_idx].tree_hasher[i][1],"]" );
}
log("State[", data_idx, "].next_parsing_string", "= ", State[data_idx].next_parsing_string);
log("State[", data_idx, "].next_parsing_number", "= ", State[data_idx].next_parsing_number);
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", data_idx, "].next_tree_hasher[", i,"]", "= ", State[data_idx].next_tree_hasher[i]);
}
log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}

Expand All @@ -62,11 +52,9 @@ template ParserHasher(DATA_BYTES, MAX_STACK_HEIGHT) {
// Debugging
for(var i = 0; i < MAX_STACK_HEIGHT; i++) {
log("State[", DATA_BYTES -1, "].next_stack[", i,"] ", "= [",State[DATA_BYTES -1].next_stack[i][0], "][", State[DATA_BYTES - 1].next_stack[i][1],"]" );
log("State[", DATA_BYTES -1, "].tree_hasher[", i,"] ", "= [",State[DATA_BYTES -1].tree_hasher[i][0], "][", State[DATA_BYTES -1].tree_hasher[i][1],"]" );
}
log("State[", DATA_BYTES - 1, "].next_parsing_string", "= ", State[DATA_BYTES-1].next_parsing_string);
log("State[", DATA_BYTES -1 , "].next_parsing_number", "= ", State[DATA_BYTES-1].next_parsing_number);
for(var i = 0; i<MAX_STACK_HEIGHT; i++) {
log("State[", DATA_BYTES -1 , "].next_tree_hashe[", i,"] ", "= ", State[DATA_BYTES-1].tree_hasher[i]);
}
log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
60 changes: 30 additions & 30 deletions circuits/test/json/parser/hash_machine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,47 @@ describe("hash_machine", () => {
});
});

console.log("[0,0] hash: ", PoseidonModular([0, 0]));
console.log("[2,0] hash: ", PoseidonModular([2, 0]));
console.log("[2,1] hash: ", PoseidonModular([2, 1]));
console.log("[1,0] hash: ", PoseidonModular([1, 0]));
// console.log("[0,0] hash: ", PoseidonModular([0, 0]));
// console.log("[2,0] hash: ", PoseidonModular([2, 0]));
// console.log("[2,1] hash: ", PoseidonModular([2, 1]));
// console.log("[1,0] hash: ", PoseidonModular([1, 0]));
// [0,0] hash: 14744269619966411208579211824598458697587494354926760081771325075741142829156n
// [2,0] hash: 17525667638260400994329361135304146970274213890416440938331684485841550124768n
// [2,1] hash: 9708419728795563670286566418307042748092204899363634976546883453490873071450n
// [1,0] hash: 18423194802802147121294641945063302532319431080857859605204660473644265519999n

// TODO: Check that the hash of the packedState.in getting the next_state_hash is correct, the stack hashes are correct.

it(`example_input`, async () => {
let filename = "example";
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a"]);
// it(`example_input`, async () => {
// let filename = "example";
// let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["a"]);

circuit = await circomkit.WitnessTester(`Parser`, {
file: "json/parser/hash_parser",
template: "ParserHasher",
params: [input.length, 7],
});
console.log("#constraints:", await circuit.getConstraintCount());
// circuit = await circomkit.WitnessTester(`Parser`, {
// file: "json/parser/hash_parser",
// template: "ParserHasher",
// params: [input.length, 7],
// });
// console.log("#constraints:", await circuit.getConstraintCount());

await circuit.expectPass({
data: input
});
});
// await circuit.expectPass({
// data: input
// });
// });


it(`spotify_input`, async () => {
let filename = "spotify";
let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["data"]);
// it(`spotify_input`, async () => {
// let filename = "spotify";
// let [input, keyUnicode, output] = readJSONInputFile(`${filename}.json`, ["data"]);

circuit = await circomkit.WitnessTester(`Parser`, {
file: "json/parser/hash_parser",
template: "ParserHasher",
params: [input.length, 7],
});
console.log("#constraints:", await circuit.getConstraintCount());
// circuit = await circomkit.WitnessTester(`Parser`, {
// file: "json/parser/hash_parser",
// template: "ParserHasher",
// params: [input.length, 7],
// });
// console.log("#constraints:", await circuit.getConstraintCount());

await circuit.expectPass({
data: input
});
});
// await circuit.expectPass({
// data: input
// });
// });
})

0 comments on commit 01691f4

Please sign in to comment.