diff --git a/circuits/test/common/index.ts b/circuits/test/common/index.ts index 8fea3d5..a5ebae5 100644 --- a/circuits/test/common/index.ts +++ b/circuits/test/common/index.ts @@ -7,22 +7,3 @@ export const circomkit = new Circomkit({ export { WitnessTester }; -export function generatePassCase(input: any, expected: any, desc: string, circuit: any) { - const description = Object.entries(input) - .map(([key, value]) => `${key} = ${value}`) - .join(", "); - - it(`(valid) witness: ${description}\n${desc}`, async () => { - await circuit.expectPass(input, expected); - }); -} - -export function generateFailCase(input: any, desc: string, circuit: any) { - const description = Object.entries(input) - .map(([key, value]) => `${key} = ${value}`) - .join(", "); - - it(`(invalid) witness: ${description}\n${desc}`, async () => { - await circuit.expectFail(input); - }); -} \ No newline at end of file diff --git a/circuits/test/parser/index.ts b/circuits/test/parser/index.ts index 95e18b7..1c5bb69 100644 --- a/circuits/test/parser/index.ts +++ b/circuits/test/parser/index.ts @@ -40,4 +40,19 @@ export const Numbers = { export const Escape = { // ASCII char: `\` BACKSLASH: 92, +}; + +export const INITIAL_IN = { + byte: 0, + pointer: 0, + stack: [0, 0, 0, 0], + parsing_string: 0, + parsing_number: 0, +}; + +export const INITIAL_OUT = { + next_pointer: INITIAL_IN.pointer, + next_stack: INITIAL_IN.stack, + next_parsing_string: INITIAL_IN.parsing_string, + next_parsing_number: INITIAL_IN.parsing_number, }; \ No newline at end of file diff --git a/circuits/test/parser/parser.test.ts b/circuits/test/parser/parser.test.ts index 3bc0e3d..d7722a1 100644 --- a/circuits/test/parser/parser.test.ts +++ b/circuits/test/parser/parser.test.ts @@ -1,5 +1,5 @@ -import { circomkit, WitnessTester, generatePassCase, generateFailCase } from "../common"; -import { Delimiters, WhiteSpace, Numbers, Escape } from '.'; +import { circomkit, WitnessTester } from "../common"; +import { Delimiters, WhiteSpace, Numbers, Escape, INITIAL_IN, INITIAL_OUT } from '.'; @@ -9,6 +9,26 @@ describe("StateUpdate", () => { ["next_pointer", "next_stack", "next_parsing_string", "next_parsing_number"] >; + function generatePassCase(input: any, expected: any, desc: string) { + const description = Object.entries(input) + .map(([key, value]) => `${key} = ${value}`) + .join(", "); + + it(`(valid) witness: ${description}\n${desc}`, async () => { + await circuit.expectPass(input, expected); + }); + } + + function generateFailCase(input: any, desc: string) { + const description = Object.entries(input) + .map(([key, value]) => `${key} = ${value}`) + .join(", "); + + it(`(invalid) witness: ${description}\n${desc}`, async () => { + await circuit.expectFail(input); + }); + } + before(async () => { circuit = await circomkit.WitnessTester(`StateUpdate`, { file: "circuits/parser", @@ -19,26 +39,11 @@ describe("StateUpdate", () => { }); - let init = { - byte: 0, - pointer: 0, - stack: [0, 0, 0, 0], - parsing_string: 0, - parsing_number: 0, - }; - let out = { - next_pointer: init.pointer, - next_stack: init.stack, - next_parsing_string: init.parsing_string, - next_parsing_number: init.parsing_number, - }; - - //-----------------------------------------------------------------------------// // Test 1: // init: ZEROS then read `do_nothing` byte // expect: ZEROS - generatePassCase(init, out, ">>>> `NUL` read", circuit); + generatePassCase(INITIAL_IN, INITIAL_OUT, ">>>> `NUL` read"); //-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------// @@ -46,9 +51,9 @@ describe("StateUpdate", () => { // init: ZEROS -> `{` is read // expect: pointer --> 1 // stack --> [1,0,0,0] - let read_start_brace = { ...init }; + let read_start_brace = { ...INITIAL_IN }; read_start_brace.byte = Delimiters.START_BRACE; - let read_start_brace_out = { ...out }; + let read_start_brace_out = { ...INITIAL_OUT }; read_start_brace_out.next_pointer = 1; read_start_brace_out.next_stack = [1, 0, 0, 0]; generatePassCase(read_start_brace, read_start_brace_out, ">>>> `{` read"); @@ -58,7 +63,7 @@ describe("StateUpdate", () => { // Test 3: // init: ZEROS -> `}` is read // expect: FAIL stack underflow - let read_end_brace = { ...init }; + let read_end_brace = { ...INITIAL_IN }; read_end_brace.byte = Delimiters.END_BRACE; generateFailCase(read_end_brace, ">>>> `}` read --> (stack underflow)"); //-----------------------------------------------------------------------------// @@ -67,11 +72,11 @@ describe("StateUpdate", () => { // Test 4: // init: pointer == 1, stack = [1,0,0,0] -> `"` is read // expect: parsing_string --> 1 - let in_object_find_key = { ...init }; + let in_object_find_key = { ...INITIAL_IN }; in_object_find_key.pointer = read_start_brace_out.next_pointer; in_object_find_key.stack = read_start_brace_out.next_stack; in_object_find_key.byte = Delimiters.QUOTE; - let in_object_find_key_out = { ...out }; + let in_object_find_key_out = { ...INITIAL_OUT }; in_object_find_key_out.next_pointer = in_object_find_key.pointer; in_object_find_key_out.next_stack = in_object_find_key.stack; in_object_find_key_out.next_parsing_string = 1; @@ -83,12 +88,12 @@ describe("StateUpdate", () => { // init: pointer == 1, stack = [1,0,0,0], parsing_string = 1 -> ` ` is read // expect: parsing_string --> 1 // in_key --> 1 - let in_key = { ...init }; + let in_key = { ...INITIAL_IN }; in_key.pointer = read_start_brace_out.next_pointer; in_key.stack = read_start_brace_out.next_stack; in_key.parsing_string = 1; in_key.byte = WhiteSpace.SPACE; - let in_key_out = { ...out }; + let in_key_out = { ...INITIAL_OUT }; in_key_out.next_pointer = in_key.pointer; in_key_out.next_stack = in_key.stack; in_key_out.next_parsing_string = 1; @@ -100,12 +105,12 @@ describe("StateUpdate", () => { // init: pointer = 1, stack = [1,0,0,0], parsing_string = 1 setup -> `"` is read // expect: parsing_string --> 0 // - let in_key_to_exit = { ...init }; + let in_key_to_exit = { ...INITIAL_IN }; in_key_to_exit.pointer = read_start_brace_out.next_pointer; in_key_to_exit.stack = read_start_brace_out.next_stack; in_key_to_exit.parsing_string = 1 in_key_to_exit.byte = Delimiters.QUOTE; - let in_key_to_exit_out = { ...out }; + let in_key_to_exit_out = { ...INITIAL_OUT }; in_key_to_exit_out.next_pointer = in_key_to_exit.pointer; in_key_to_exit_out.next_stack = in_key_to_exit.stack; generatePassCase(in_key_to_exit, in_key_to_exit_out, "`\"` read"); @@ -114,11 +119,11 @@ describe("StateUpdate", () => { //-----------------------------------------------------------------------------// // Test 7: // init: pointer = 1, stack = [1,0,0,0] -> `:` is read - let parsed_key_wait_to_parse_value = { ...init }; + let parsed_key_wait_to_parse_value = { ...INITIAL_IN }; parsed_key_wait_to_parse_value.pointer = read_start_brace_out.next_pointer; parsed_key_wait_to_parse_value.stack = read_start_brace_out.next_stack; parsed_key_wait_to_parse_value.byte = Delimiters.COLON; - let parsed_key_wait_to_parse_value_out = { ...out }; + let parsed_key_wait_to_parse_value_out = { ...INITIAL_OUT }; parsed_key_wait_to_parse_value_out.next_pointer = 2; parsed_key_wait_to_parse_value_out.next_stack = [1, 3, 0, 0]; generatePassCase(parsed_key_wait_to_parse_value, parsed_key_wait_to_parse_value_out, ">>>> `:` read"); diff --git a/circuits/test/parser/stack.test.ts b/circuits/test/parser/stack.test.ts index 56f622e..dca3232 100644 --- a/circuits/test/parser/stack.test.ts +++ b/circuits/test/parser/stack.test.ts @@ -1,5 +1,5 @@ import { circomkit, WitnessTester } from "../common"; -import { Delimiters, WhiteSpace, Numbers, Escape } from './constants'; +import { Delimiters, WhiteSpace, Numbers, Escape, INITIAL_IN, INITIAL_OUT } from '.'; describe("GetTopOfStack", () => { let circuit: WitnessTester<["stack", "pointer"], ["out"]>; @@ -18,20 +18,51 @@ describe("GetTopOfStack", () => { { out: 4 }, ); }); +}); +describe("StateUpdate :: RewriteStack", () => { + let circuit: WitnessTester< + ["byte", "pointer", "stack", "parsing_string", "parsing_number"], + ["next_pointer", "next_stack", "next_parsing_string", "next_parsing_number"] + >; + before(async () => { + circuit = await circomkit.WitnessTester(`GetTopOfStack`, { + file: "circuits/parser", + template: "StateUpdate", + params: [4], + }); + console.log("#constraints:", await circuit.getConstraintCount()); + }); + function generatePassCase(input: any, expected: any, desc: string) { + const description = Object.entries(input) + .map(([key, value]) => `${key} = ${value}`) + .join(", "); + it(`(valid) witness: ${description}\n${desc}`, async () => { + await circuit.expectPass(input, expected); + }); + } + function generateFailCase(input: any, desc: string) { + const description = Object.entries(input) + .map(([key, value]) => `${key} = ${value}`) + .join(", "); + + it(`(invalid) witness: ${description}\n${desc}`, async () => { + await circuit.expectFail(input); + }); + } // TODO: Test stack fully works with brackets too // Test 7: Stack Management // init: read `{`, read another `{` // expect: pointer --> 2 // stack --> [1,1,0,0] - let in_object = { ...init }; - in_object.pointer = read_start_brace_out.next_pointer; - in_object.stack = read_start_brace_out.next_stack; + let in_object = { ...INITIAL_IN }; + in_object.pointer = 1; + in_object.stack = [1, 0, 0, 0]; in_object.byte = Delimiters.START_BRACE; - let in_object_out = { ...out }; + let in_object_out = { ...INITIAL_OUT }; in_object_out.next_pointer = 2; in_object_out.next_stack = [1, 1, 0, 0]; generatePassCase(in_object, in_object_out, ">>>> `{` read"); @@ -40,24 +71,22 @@ describe("GetTopOfStack", () => { // init: read `{` then read`}` // expect: pointer --> 0 // stack --> [0, 0, 0, 0] - let in_object_to_leave = { ...init }; - in_object_to_leave.pointer = read_start_brace_out.next_pointer; - in_object_to_leave.stack = read_start_brace_out.next_stack; + let in_object_to_leave = { ...INITIAL_IN }; + in_object_to_leave.pointer = 1; + in_object_to_leave.stack = [1, 0, 0, 0]; in_object_to_leave.byte = Delimiters.END_BRACE; - let in_object_to_leave_out = { ...out }; - in_object_to_leave_out.next_pointer = 0; - in_object_to_leave_out.next_stack = [0, 0, 0, 0]; + let in_object_to_leave_out = { ...INITIAL_OUT }; generatePassCase(in_object_to_leave, in_object_to_leave_out, ">>>> `}` read"); // Test 9: Stack Management // init: read `{`, then read `[` // expect: pointer --> 2 // stack --> [1,2,0,0] - let in_object_to_read_start_bracket = { ...init }; + let in_object_to_read_start_bracket = { ...INITIAL_IN }; in_object_to_read_start_bracket.byte = Delimiters.START_BRACKET; in_object_to_read_start_bracket.pointer = 1; in_object_to_read_start_bracket.stack = [1, 0, 0, 0]; - let in_object_to_read_start_bracket_out = { ...out }; + let in_object_to_read_start_bracket_out = { ...INITIAL_OUT }; in_object_to_read_start_bracket_out.next_pointer = 2; in_object_to_read_start_bracket_out.next_stack = [1, 2, 0, 0]; generatePassCase(in_object_to_read_start_bracket, in_object_to_read_start_bracket_out, ">>>> `[` read"); @@ -66,7 +95,7 @@ describe("GetTopOfStack", () => { // init: read 4x `{`, then read `{` // expect: pointer --> 4 // stack --> [1,1,1,1] - let in_max_stack = { ...init }; + let in_max_stack = { ...INITIAL_IN }; in_max_stack.byte = Delimiters.START_BRACE; in_max_stack.pointer = 4; in_max_stack.stack = [1, 1, 1, 1]; @@ -76,7 +105,7 @@ describe("GetTopOfStack", () => { // init: read 4x `{`, then read `[` // expect: pointer --> 4 // stack --> [1,1,1,1] - let in_max_stack_2 = { ...init }; + let in_max_stack_2 = { ...INITIAL_IN }; in_max_stack_2.byte = Delimiters.START_BRACKET; in_max_stack_2.pointer = 4; in_max_stack_2.stack = [1, 1, 1, 1]; @@ -86,11 +115,11 @@ describe("GetTopOfStack", () => { // init: read `{` and `[`, then read `]` // expect: pointer --> 2 // stack --> [1,0,0,0] - let in_object_and_array = { ...init }; + let in_object_and_array = { ...INITIAL_IN }; in_object_and_array.byte = Delimiters.END_BRACKET; in_object_and_array.pointer = 2; in_object_and_array.stack = [1, 2, 0, 0]; - let in_object_and_array_out = { ...out }; + let in_object_and_array_out = { ...INITIAL_OUT }; in_object_and_array_out.next_pointer = 1; in_object_and_array_out.next_stack = [1, 0, 0, 0]; generatePassCase(in_object_and_array, in_object_and_array_out, ">>>> `]` read"); @@ -99,11 +128,11 @@ describe("GetTopOfStack", () => { // init: read `{` and `:`, then read `,` // expect: pointer --> 2 // stack --> [1,3,0,0] - let in_object_and_value = { ...init }; + let in_object_and_value = { ...INITIAL_IN }; in_object_and_value.byte = Delimiters.COMMA; in_object_and_value.pointer = 2; in_object_and_value.stack = [1, 3, 0, 0]; - let in_object_and_value_out = { ...out }; + let in_object_and_value_out = { ...INITIAL_OUT }; in_object_and_value_out.next_pointer = 1; in_object_and_value_out.next_stack = [1, 0, 0, 0]; generatePassCase(in_object_and_value, in_object_and_value_out, ">>>> `,` read"); @@ -112,30 +141,23 @@ describe("GetTopOfStack", () => { // init: read `{` and `:`, then read `,` // expect: pointer --> 2 // stack --> [1,3,0,0] - let in_object_and_value_to_leave_object = { ...init }; + let in_object_and_value_to_leave_object = { ...INITIAL_IN }; in_object_and_value_to_leave_object.byte = Delimiters.END_BRACE; in_object_and_value_to_leave_object.pointer = 2; in_object_and_value_to_leave_object.stack = [1, 3, 0, 0]; - let in_object_and_value_to_leave_object_out = { ...out }; + let in_object_and_value_to_leave_object_out = { ...INITIAL_OUT }; in_object_and_value_to_leave_object_out.next_pointer = 0; in_object_and_value_to_leave_object_out.next_stack = [0, 0, 0, 0]; generatePassCase(in_object_and_value_to_leave_object, in_object_and_value_to_leave_object_out, ">>>> `,` read"); - - - - - - - //-----------------------------------------------------------------------------// // Test SOMETHING: // init: pointer = 1, stack = [1,2,0,0] -> `,` is read - let inside_array = { ...init }; + let inside_array = { ...INITIAL_IN }; inside_array.pointer = 2; inside_array.stack = [1, 2, 0, 0]; inside_array.byte = Delimiters.COMMA; - let inside_array_out = { ...out }; + let inside_array_out = { ...INITIAL_OUT }; inside_array_out.next_pointer = 2; inside_array_out.next_stack = [1, 2, 0, 0]; generatePassCase(inside_array, inside_array_out, ">>>> `,` read");