Skip to content

Commit 10c8fd4

Browse files
authored
fix: empty array and object (#108)
* test: circom empties * fix: rust parser empty object
1 parent fd29efa commit 10c8fd4

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

circuits/test/json/extraction.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,66 @@ describe("JSON Extraction", () => {
480480
console.log("> Fourth subtest passed.");
481481
});
482482

483+
it(`input: empty`, async () => {
484+
let filename = "empty";
485+
let [input, _keyUnicode, _output] = readJSONInputFile(`${filename}.json`, []);
486+
let input_padded = input.concat(Array(DATA_BYTES - input.length).fill(-1));
487+
488+
// Test `{}` in "empty" key
489+
let keySequence: JsonMaskType[] = [
490+
{ type: "Object", value: strToBytes("empty") },
491+
];
492+
let [stack, treeHashes] = jsonTreeHasher(mock_ct_digest, keySequence, MAX_STACK_HEIGHT);
493+
console.log(treeHashes);
494+
let sequence_digest = compressTreeHash(mock_ct_digest, [stack, treeHashes]);
495+
let sequence_digest_hashed = poseidon1([sequence_digest]);
496+
497+
let value_digest = BigInt(0);
498+
499+
let data_digest = PolynomialDigest(input, mock_ct_digest, BigInt(0));
500+
501+
let state = Array(MAX_STACK_HEIGHT * 4 + 4).fill(0);
502+
let state_digest = PolynomialDigest(state, mock_ct_digest, BigInt(0));
503+
504+
let step_in = [data_digest, 0, 0, 0, 0, 0, 0, 1, state_digest, sequence_digest_hashed, 0];
505+
506+
let json_extraction_step_out = await hash_parser.compute({
507+
data: input_padded,
508+
ciphertext_digest: mock_ct_digest,
509+
sequence_digest,
510+
value_digest,
511+
step_in,
512+
state,
513+
}, ["step_out"]);
514+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[0], value_digest);
515+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[7], modPow(mock_ct_digest, BigInt(input.length)));
516+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[9], sequence_digest_hashed);
517+
console.log("> First subtest passed.");
518+
519+
// Test `[]` in "arr" key
520+
keySequence = [
521+
{ type: "Object", value: strToBytes("arr") },
522+
];
523+
[stack, treeHashes] = jsonTreeHasher(mock_ct_digest, keySequence, MAX_STACK_HEIGHT);
524+
sequence_digest = compressTreeHash(mock_ct_digest, [stack, treeHashes]);
525+
sequence_digest_hashed = poseidon1([sequence_digest]);
526+
value_digest = BigInt(0);
527+
step_in = [data_digest, 0, 0, 0, 0, 0, 0, 1, state_digest, sequence_digest_hashed, 0];;
528+
529+
json_extraction_step_out = await hash_parser.compute({
530+
data: input_padded,
531+
ciphertext_digest: mock_ct_digest,
532+
sequence_digest,
533+
value_digest,
534+
step_in,
535+
state,
536+
}, ["step_out"]);
537+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[0], value_digest);
538+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[7], modPow(mock_ct_digest, BigInt(input.length)));
539+
assert.deepEqual((json_extraction_step_out.step_out as BigInt[])[9], sequence_digest_hashed);
540+
console.log("> Second subtest passed.");
541+
});
542+
483543
it(`input: spotify`, async () => {
484544
let filename = "spotify";
485545
let [input, _keyUnicode, _output] = readJSONInputFile(`${filename}.json`, []);

examples/json/empty.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"object":{},"arr":[]}

witness-generator/src/json/parser.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ pub fn parse<const MAX_STACK_HEIGHT: usize>(
166166
)),
167167
},
168168
END_BRACE => match (machine.clone().status, machine.current_location()) {
169-
(Status::None | Status::ParsingPrimitive(_), Location::ObjectValue) => {
169+
(
170+
Status::None | Status::ParsingPrimitive(_),
171+
Location::ObjectKey | Location::ObjectValue,
172+
) => {
170173
machine.location[machine.pointer() - 1] = Location::None;
171174
machine.status = Status::None;
172175
machine.clear_label_stack();
@@ -387,6 +390,7 @@ mod tests {
387390
r#"{"null": null, "false": false, "true": true, "num1": 2.0E-1, "num2": 2.0e+1}"#
388391
)]
389392
#[case::primitives_array(r#"[null,false,true,2.0E-1,2.0e+1]"#)]
393+
#[case::empty(r#"{"object":{},"arr":[]}"#)]
390394
fn test_json_parser_valid(#[case] input: &str) {
391395
let polynomial_input = create_polynomial_input();
392396

0 commit comments

Comments
 (0)