From e57c07e10d4448289c90cb74849f7f5cb565b82c Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 28 Nov 2023 10:38:26 +0000 Subject: [PATCH 1/3] fix: array witnesses in numerial rather than ascii order --- tooling/noir_js_backend_barretenberg/src/public_inputs.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tooling/noir_js_backend_barretenberg/src/public_inputs.ts b/tooling/noir_js_backend_barretenberg/src/public_inputs.ts index fb7fee59beb..37bc5b13012 100644 --- a/tooling/noir_js_backend_barretenberg/src/public_inputs.ts +++ b/tooling/noir_js_backend_barretenberg/src/public_inputs.ts @@ -1,7 +1,7 @@ import { Abi, WitnessMap } from '@noir-lang/types'; export function flattenPublicInputs(publicInputs: WitnessMap): string[] { - const publicInputIndices = [...publicInputs.keys()].sort(); + const publicInputIndices = [...publicInputs.keys()].sort((a, b) => a - b); const flattenedPublicInputs = publicInputIndices.map((index) => publicInputs.get(index) as string); return flattenedPublicInputs; } @@ -31,7 +31,9 @@ export function deflattenPublicInputs(flattenedPublicInputs: Uint8Array, abi: Ab // We now have an array of witness indices which have been deduplicated and sorted in ascending order. // The elements of this array should correspond to the elements of `flattenedPublicInputs` so that we can build up a `WitnessMap`. - const public_input_witnesses = [...new Set(public_parameter_witnesses.concat(return_value_witnesses))].sort(); + const public_input_witnesses = [...new Set(public_parameter_witnesses.concat(return_value_witnesses))].sort( + (a, b) => a - b, + ); const publicInputs: WitnessMap = new Map(); public_input_witnesses.forEach((witness_index, index) => { From bb0b00950a74b70a5ff068b954c7f432707faa5a Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 28 Nov 2023 13:03:02 +0000 Subject: [PATCH 2/3] chore: add test for public input flattening --- .github/workflows/test-js-packages.yml | 27 ++++++ .../.mocharc.json | 11 +++ .../noir_js_backend_barretenberg/package.json | 4 + .../test/public_input_deflattening.test.ts | 93 +++++++++++++++++++ yarn.lock | 3 + 5 files changed, 138 insertions(+) create mode 100644 tooling/noir_js_backend_barretenberg/.mocharc.json create mode 100644 tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts diff --git a/.github/workflows/test-js-packages.yml b/.github/workflows/test-js-packages.yml index 519c94f3de0..9ac61f34203 100644 --- a/.github/workflows/test-js-packages.yml +++ b/.github/workflows/test-js-packages.yml @@ -203,6 +203,32 @@ jobs: - name: Run browser tests run: yarn workspace @noir-lang/noirc_abi test:browser + test-noir-js-backend-barretenberg: + needs: [build-noirc-abi] + name: noir-js-backend-barretenberg + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download wasm package artifact + uses: actions/download-artifact@v3 + with: + name: noirc_abi_wasm + path: ./tooling/noirc_abi_wasm + + - name: Install Yarn dependencies + uses: ./.github/actions/setup + + - name: Build noir_js_types + run: yarn workspace @noir-lang/types build + + - name: Run barretenberg wrapper tests + run: | + yarn workspace @noir-lang/backend_barretenberg test + test-noir-js: needs: [build-acvm-js, build-noirc-abi] name: Noir JS @@ -401,6 +427,7 @@ jobs: - test-acvm_js-node - test-acvm_js-browser - test-noirc-abi + - test-noir-js-backend-barretenberg - test-noir-js - test-source-resolver - test-noir-wasm diff --git a/tooling/noir_js_backend_barretenberg/.mocharc.json b/tooling/noir_js_backend_barretenberg/.mocharc.json new file mode 100644 index 00000000000..e1023f56327 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/.mocharc.json @@ -0,0 +1,11 @@ +{ + "require": "ts-node/register", + "loader": "ts-node/esm", + "extensions": [ + "ts", + "cjs" + ], + "spec": [ + "test/**/*.test.ts*" + ] +} diff --git a/tooling/noir_js_backend_barretenberg/package.json b/tooling/noir_js_backend_barretenberg/package.json index fbd89d7d350..baf8c0f58fd 100644 --- a/tooling/noir_js_backend_barretenberg/package.json +++ b/tooling/noir_js_backend_barretenberg/package.json @@ -25,6 +25,7 @@ "generate:package": "bash ./fixup.sh", "build": "yarn clean && tsc && tsc -p ./tsconfig.cjs.json && yarn generate:package", "clean": "rm -rf ./lib", + "test": "mocha --timeout 25000 --exit --config ./.mocharc.json", "prettier": "prettier 'src/**/*.ts'", "prettier:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "nightly:version": "jq --arg new_version \"-$(git rev-parse --short HEAD)$1\" '.version = .version + $new_version' package.json > package-tmp.json && mv package-tmp.json package.json", @@ -39,9 +40,12 @@ "devDependencies": { "@types/node": "^20.6.2", "@types/prettier": "^3", + "chai": "^4.3.8", "eslint": "^8.50.0", "eslint-plugin-prettier": "^5.0.0", + "mocha": "^10.2.0", "prettier": "3.0.3", + "ts-node": "^10.9.1", "typescript": "5.1.5" } } diff --git a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts new file mode 100644 index 00000000000..559f32f1942 --- /dev/null +++ b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts @@ -0,0 +1,93 @@ +import { Abi } from '@noir-lang/types'; +import { expect } from 'chai'; +import { flattenPublicInputsAsArray, deflattenPublicInputs, flattenPublicInputs } from '../src/public_inputs.js'; + +const abi: Abi = { + parameters: [ + { + name: 'pub_field', + type: { + kind: 'field', + }, + visibility: 'public', + }, + { + name: 'array_with_returned_element', + type: { + kind: 'array', + type: { + kind: 'field', + }, + length: 10, + }, + visibility: 'private', + }, + ], + param_witnesses: { + pub_field: [ + { + start: 1, + end: 2, + }, + ], + array_with_returned_element: [ + { + start: 2, + end: 12, + }, + ], + }, + return_type: { + kind: 'tuple', + fields: [ + { + kind: 'field', + }, + { + kind: 'field', + }, + { + kind: 'field', + }, + ], + }, + return_witnesses: [2, 13, 13], +}; + +it('flattens a witness map in order of its witness indices', async () => { + // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order + // then the witness values will be sorted incorrectly. + const public_input_indices = [1, 13, 2]; + + const witness_map = new Map( + public_input_indices.map((witness_index) => [ + witness_index, + '0x' + BigInt(witness_index).toString(16).padStart(64, '0'), + ]), + ); + + const flattened_public_inputs = flattenPublicInputs(witness_map); + expect(flattened_public_inputs).to.be.deep.eq([ + '0x0000000000000000000000000000000000000000000000000000000000000001', + '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x000000000000000000000000000000000000000000000000000000000000000d', + ]); +}); + +it('recovers the original witness map when deflattening a public input array', async () => { + // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order + // then the witness values will be sorted incorrectly. + const public_input_indices = [1, 13, 2]; + + const witness_map = new Map( + public_input_indices.map((witness_index) => [ + witness_index, + '0x' + BigInt(witness_index).toString(16).padStart(64, '0'), + ]), + ); + + const flattened_public_inputs = flattenPublicInputsAsArray(witness_map); + const deflattened_public_inputs = deflattenPublicInputs(flattened_public_inputs, abi); + + expect(deflattened_public_inputs).to.be.deep.eq(witness_map); +}); diff --git a/yarn.lock b/yarn.lock index fd2dd3a40d8..b21d1256eff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3438,10 +3438,13 @@ __metadata: "@noir-lang/types": "workspace:*" "@types/node": ^20.6.2 "@types/prettier": ^3 + chai: ^4.3.8 eslint: ^8.50.0 eslint-plugin-prettier: ^5.0.0 fflate: ^0.8.0 + mocha: ^10.2.0 prettier: 3.0.3 + ts-node: ^10.9.1 typescript: 5.1.5 languageName: unknown linkType: soft From db1ff95c7647ce31381ca3cbad669b86c2633750 Mon Sep 17 00:00:00 2001 From: Tom French Date: Tue, 28 Nov 2023 13:13:03 +0000 Subject: [PATCH 3/3] chore: improve test input --- .../test/public_input_deflattening.test.ts | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts index 559f32f1942..98189eaed5f 100644 --- a/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts +++ b/tooling/noir_js_backend_barretenberg/test/public_input_deflattening.test.ts @@ -4,13 +4,6 @@ import { flattenPublicInputsAsArray, deflattenPublicInputs, flattenPublicInputs const abi: Abi = { parameters: [ - { - name: 'pub_field', - type: { - kind: 'field', - }, - visibility: 'public', - }, { name: 'array_with_returned_element', type: { @@ -22,17 +15,24 @@ const abi: Abi = { }, visibility: 'private', }, + { + name: 'pub_field', + type: { + kind: 'field', + }, + visibility: 'public', + }, ], param_witnesses: { - pub_field: [ + array_with_returned_element: [ { start: 1, - end: 2, + end: 11, }, ], - array_with_returned_element: [ + pub_field: [ { - start: 2, + start: 11, end: 12, }, ], @@ -57,7 +57,7 @@ const abi: Abi = { it('flattens a witness map in order of its witness indices', async () => { // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order // then the witness values will be sorted incorrectly. - const public_input_indices = [1, 13, 2]; + const public_input_indices = [2, 13, 11]; const witness_map = new Map( public_input_indices.map((witness_index) => [ @@ -68,8 +68,8 @@ it('flattens a witness map in order of its witness indices', async () => { const flattened_public_inputs = flattenPublicInputs(witness_map); expect(flattened_public_inputs).to.be.deep.eq([ - '0x0000000000000000000000000000000000000000000000000000000000000001', '0x0000000000000000000000000000000000000000000000000000000000000002', + '0x000000000000000000000000000000000000000000000000000000000000000b', '0x000000000000000000000000000000000000000000000000000000000000000d', ]); }); @@ -77,7 +77,7 @@ it('flattens a witness map in order of its witness indices', async () => { it('recovers the original witness map when deflattening a public input array', async () => { // Note that these are not in ascending order. This means that if we read from `witness_map` in insertion order // then the witness values will be sorted incorrectly. - const public_input_indices = [1, 13, 2]; + const public_input_indices = [2, 13, 11]; const witness_map = new Map( public_input_indices.map((witness_index) => [