From 240152983772a87602e71571198ad778a93fc9a2 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 5 May 2025 11:59:15 +0000 Subject: [PATCH 1/3] fix: Ordering of items in callstacks --- tooling/noir_js/src/debug.ts | 3 ++- tooling/noir_js/test/node/execute.test.ts | 18 ++++++++++++++++-- .../assert_msg_runtime/src/main.nr | 4 ++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tooling/noir_js/src/debug.ts b/tooling/noir_js/src/debug.ts index 4f915071388..92170e3c207 100644 --- a/tooling/noir_js/src/debug.ts +++ b/tooling/noir_js/src/debug.ts @@ -101,7 +101,8 @@ function getCallStackFromLocationNode( const line = previousLines.length; const column = previousLines[previousLines.length - 1].length + 1; - result.push({ + // Unshift since we are exploring child nodes first + result.unshift({ filePath: path, line, column, diff --git a/tooling/noir_js/test/node/execute.test.ts b/tooling/noir_js/test/node/execute.test.ts index f657adefd95..c25f02af4bb 100644 --- a/tooling/noir_js/test/node/execute.test.ts +++ b/tooling/noir_js/test/node/execute.test.ts @@ -40,8 +40,22 @@ it('circuit with a fmt string assert message should fail with the resolved asser } catch (error) { const knownError = error as ErrorWithPayload; expect(knownError.message).to.equal('Circuit execution failed: Expected x < y but got 10 < 5'); - expect(knownError.noirCallStack).to.have.lengthOf(1); - expect(knownError.noirCallStack![0]).to.match(/^at x < y \(.*assert_msg_runtime\/src\/main.nr:3:12\)$/); + } +}); + +it('circuit with a nested assertion should fail with the resolved call stack', async () => { + try { + await new Noir(assert_msg_runtime).execute({ + x: '10', + y: '5', + }); + } catch (error) { + const knownError = error as ErrorWithPayload; + expect(knownError.noirCallStack).to.have.lengthOf(2); + expect(knownError.noirCallStack![0]).to.match( + /^at make_assertion\(x, y\) \(.*assert_msg_runtime\/src\/main.nr:2:5\)$/, + ); + expect(knownError.noirCallStack![1]).to.match(/^at x < y \(.*assert_msg_runtime\/src\/main.nr:7:12\)$/); } }); diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr index 0bcd5c58c24..e9b980afa70 100644 --- a/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr +++ b/tooling/noir_js/test/noir_compiled_examples/assert_msg_runtime/src/main.nr @@ -1,4 +1,8 @@ fn main(x: u64, y: pub u64) { + make_assertion(x, y); +} + +fn make_assertion(x: u64, y: u64) { // A fmtstr assertion message is used to show that noirJS will decode the error payload as a string. assert(x < y, f"Expected x < y but got {x} < {y}"); } From dfcb309cdcf656b830167ae74474781350b3c1c2 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 5 May 2025 12:39:33 +0000 Subject: [PATCH 2/3] fix ordering for acir=>brillig situations --- .../noir_js/scripts/compile_test_programs.sh | 2 ++ tooling/noir_js/src/debug.ts | 8 ++++---- tooling/noir_js/test/node/execute.test.ts | 18 ++++++++++++++++++ .../assert_inside_brillig_nested/Nargo.toml | 5 +++++ .../assert_inside_brillig_nested/src/main.nr | 17 +++++++++++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/Nargo.toml create mode 100644 tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/src/main.nr diff --git a/tooling/noir_js/scripts/compile_test_programs.sh b/tooling/noir_js/scripts/compile_test_programs.sh index 738db98bc06..9776a0a5020 100755 --- a/tooling/noir_js/scripts/compile_test_programs.sh +++ b/tooling/noir_js/scripts/compile_test_programs.sh @@ -8,3 +8,5 @@ $NARGO --program-dir ./test/noir_compiled_examples/assert_msg_runtime compile -- $NARGO --program-dir ./test/noir_compiled_examples/fold_fibonacci compile --force --pedantic-solving $NARGO --program-dir ./test/noir_compiled_examples/assert_raw_payload compile --force --pedantic-solving $NARGO --program-dir ./test/noir_compiled_examples/databus compile --force --pedantic-solving +# Compile with no inlining to test runtime call stacks +$NARGO --program-dir ./test/noir_compiled_examples/assert_inside_brillig_nested compile --force --pedantic-solving --inliner-aggressiveness -9223372036854775808 \ No newline at end of file diff --git a/tooling/noir_js/src/debug.ts b/tooling/noir_js/src/debug.ts index 92170e3c207..2a0ae2e9176 100644 --- a/tooling/noir_js/src/debug.ts +++ b/tooling/noir_js/src/debug.ts @@ -71,13 +71,13 @@ function resolveOpcodeLocations( ); // Adds the acir call stack if the last location is a brillig opcode if (locations.length > 0) { - const runtimeLocations = opcodeLocations[opcodeLocations.length - 1].split('.'); - if (runtimeLocations.length === 2) { - const acirCallstackId = debug.acir_locations[runtimeLocations[0]]; + const decomposedOpcodeLocation = opcodeLocations[opcodeLocations.length - 1].split('.'); + if (decomposedOpcodeLocation.length === 2) { + const acirCallstackId = debug.acir_locations[decomposedOpcodeLocation[0]]; if (acirCallstackId !== undefined) { const callStack = debug.location_tree.locations[acirCallstackId]; const acirCallstack = getCallStackFromLocationNode(callStack, debug.location_tree.locations, files); - locations = locations.concat(acirCallstack); + locations = acirCallstack.concat(locations); } } } diff --git a/tooling/noir_js/test/node/execute.test.ts b/tooling/noir_js/test/node/execute.test.ts index c25f02af4bb..23f7e2d4a24 100644 --- a/tooling/noir_js/test/node/execute.test.ts +++ b/tooling/noir_js/test/node/execute.test.ts @@ -3,6 +3,7 @@ import assert_msg_json from '../noir_compiled_examples/assert_msg_runtime/target import fold_fibonacci_json from '../noir_compiled_examples/fold_fibonacci/target/fold_fibonacci.json' assert { type: 'json' }; import assert_raw_payload_json from '../noir_compiled_examples/assert_raw_payload/target/assert_raw_payload.json' assert { type: 'json' }; import databus_json from '../noir_compiled_examples/databus/target/databus.json' assert { type: 'json' }; +import assert_inside_brillig_nested_json from '../noir_compiled_examples/assert_inside_brillig_nested/target/assert_inside_brillig_nested.json' assert { type: 'json' }; import { Noir, ErrorWithPayload } from '@noir-lang/noir_js'; import { CompiledCircuit } from '@noir-lang/types'; @@ -12,6 +13,7 @@ const assert_lt_program = assert_lt_json as CompiledCircuit; const assert_msg_runtime = assert_msg_json as CompiledCircuit; const fold_fibonacci_program = fold_fibonacci_json as CompiledCircuit; const databus_program = databus_json as CompiledCircuit; +const assert_inside_brillig_nested = assert_inside_brillig_nested_json as CompiledCircuit; it('executes a single-ACIR program correctly', async () => { const inputs = { @@ -59,6 +61,22 @@ it('circuit with a nested assertion should fail with the resolved call stack', a } }); +it('circuit with a nested assertion inside brillig should fail with the resolved call stack', async () => { + try { + await new Noir(assert_inside_brillig_nested).execute({ + x: '10', + }); + } catch (error) { + const knownError = error as ErrorWithPayload; + const expectedStack = ['acir_wrapper(x)', 'brillig_entrypoint(x)', 'brillig_nested(x)', 'x < 10']; + expect(knownError.noirCallStack).to.have.lengthOf(expectedStack.length); + + for (let i = 0; i < expectedStack.length; i++) { + expect(knownError.noirCallStack![i]).to.contain(expectedStack[i]); + } + } +}); + it('circuit with a raw assert payload should fail with the decoded payload', async () => { const inputs = { x: '7', diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/Nargo.toml b/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/Nargo.toml new file mode 100644 index 00000000000..a96be316b2f --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/Nargo.toml @@ -0,0 +1,5 @@ +[package] +name = "assert_inside_brillig_nested" +type = "bin" +authors = [""] +[dependencies] diff --git a/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/src/main.nr b/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/src/main.nr new file mode 100644 index 00000000000..a121ef0f8a3 --- /dev/null +++ b/tooling/noir_js/test/noir_compiled_examples/assert_inside_brillig_nested/src/main.nr @@ -0,0 +1,17 @@ +fn main(x: u64) { + acir_wrapper(x); +} + +fn acir_wrapper(x: u64) { + unsafe { + brillig_entrypoint(x); + } +} + +unconstrained fn brillig_entrypoint(x: u64) { + brillig_nested(x); +} + +unconstrained fn brillig_nested(x: u64) { + assert(x < 10); +} From 468020130b2ee56503e2f0f74daf5905a684a474 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Mon, 5 May 2025 18:18:01 +0000 Subject: [PATCH 3/3] push and reverse --- tooling/noir_js/src/debug.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tooling/noir_js/src/debug.ts b/tooling/noir_js/src/debug.ts index 2a0ae2e9176..7003bd4abbe 100644 --- a/tooling/noir_js/src/debug.ts +++ b/tooling/noir_js/src/debug.ts @@ -101,8 +101,7 @@ function getCallStackFromLocationNode( const line = previousLines.length; const column = previousLines[previousLines.length - 1].length + 1; - // Unshift since we are exploring child nodes first - result.unshift({ + result.push({ filePath: path, line, column, @@ -111,7 +110,8 @@ function getCallStackFromLocationNode( callStack = location_tree[callStack.parent]; } - return result; + // Reverse since we explored the child nodes first + return result.reverse(); } /** * Extracts the call stack from the location of a failing opcode and the debug metadata.