Skip to content

Commit

Permalink
chore: Add noir_wasm testing workflow (#1921)
Browse files Browse the repository at this point in the history
* Edit workflow

* Output built directory

* Fix noir_wasm copy

* Fix workflow

* Add mkdir to workflow

* Remove logs

* chore: Ensure that CLI and wasm compilers are sync in `noir_wasm_testing` (#2079)

---------

Co-authored-by: jonybur <jobur93@gmail.com>

* Update .github/workflows/wasm.yml

* chore: run browser tests rather than nodejs tests

* chore: fix test command in CI

* chore: bring noir-wasm-testing repo contents into wasm crate

---------

Co-authored-by: jonybur <jobur93@gmail.com>

* chore: update compile command to handle not being at repo root

* chore: remove unnecessary checkout

* chore: update location to look for nargo binary

* chore: add missing $

* chore: remove self-referential dependency

* chore: switch to `noir-lang/noir-source-resolver` version which exists

* chore: place downloaded wasm artifact in `crates/wasm` so it can resolve the resolver

* Revisions

* chore: fix CI workflow

* chore: remove usage of `matrix.target`

* chore: fix path to binary

* chore: remove unwanted printing when compiling noir program

* chore: update `Nargo.toml` to be compliant with new format

* chore: remove unnecessary checkout

* chore: add todo to workflow

* Update .github/workflows/wasm.yml

* Update crates/wasm/noir-script/src/main.nr

* Update crates/wasm/test/browser/index.test.ts

---------

Co-authored-by: TomAFrench <tom@tomfren.ch>
Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 7, 2023
1 parent 44df932 commit 08683e1
Show file tree
Hide file tree
Showing 14 changed files with 4,000 additions and 8 deletions.
137 changes: 135 additions & 2 deletions .github/workflows/wasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,90 @@ concurrency:
cancel-in-progress: true

jobs:
build:
name: Build Wasm
# TODO: Replace this step with downloading a wasm binary from a set release of Barretenberg
build-barretenberg:
runs-on: ubuntu-latest
steps:
- name: Checkout Noir repo
uses: actions/checkout@v3

- name: Collect locked barretenberg rev
run: |
echo "BB_REV=$(jq -r .nodes.barretenberg.locked.rev ./flake.lock)" >> $GITHUB_ENV
echo "BB_REV is ${{ env.BB_REV }}"
- uses: cachix/install-nix-action@v20
with:
nix_path: nixpkgs=channel:nixos-22.11
github_access_token: ${{ secrets.GITHUB_TOKEN }}

- uses: cachix/cachix-action@v12
with:
name: barretenberg
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"

# Upload does not work with symlinks, using this workaround:
# https://github.com/actions/upload-artifact/issues/92#issuecomment-1080347032
- name: Build barretenberg as libbarretenberg-wasm32
run: |
echo "BB_REV is ${{ env.BB_REV }}"
nix build "github:AztecProtocol/barretenberg/${{ env.BB_REV }}#wasm32"
echo "ARTIFACT_UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: libbarretenberg-wasm32
path: ${{ env.ARTIFACT_UPLOAD_PATH }}
retention-days: 3

build-nargo:
needs: [build-barretenberg]
runs-on: ubuntu-22.04

steps:
- name: Checkout Noir repo
uses: actions/checkout@v3

- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Download artifact
uses: actions/download-artifact@v3
with:
name: libbarretenberg-wasm32
path: ${{ github.workspace }}/libbarretenberg-wasm32

- name: Setup toolchain
uses: dtolnay/rust-toolchain@1.66.0

- name: Build Nargo
env:
BARRETENBERG_BIN_DIR: ${{ github.workspace }}/libbarretenberg-wasm32/bin
run: |
cargo build --package nargo_cli --release --no-default-features --features plonk_bn254_wasm
- name: Package artifacts
run: |
mkdir dist
cp ./target/release/nargo ./dist/nargo
7z a -ttar -so -an ./dist/* | 7z a -si ./nargo-x86_64-unknown-linux-gnu.tar.gz
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: nargo
path: ./dist/*
retention-days: 3

build-wasm:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
Expand All @@ -25,3 +107,54 @@ jobs:
- name: Build wasm package
run: |
nix build -L .#wasm
- name: Dereference symlink
run: echo "UPLOAD_PATH=$(readlink -f result)" >> $GITHUB_ENV

- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: noir_wasm
path: ${{ env.UPLOAD_PATH }}
retention-days: 3

test:
needs: [build-wasm, build-nargo]
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout noir-lang/noir
uses: actions/checkout@v3

- name: Download wasm package artifact
uses: actions/download-artifact@v3
with:
name: noir_wasm
path: ./crates/wasm/dist

- name: Download nargo binary
uses: actions/download-artifact@v3
with:
name: nargo
path: ./nargo

- name: Compile test program with Nargo CLI
working-directory: ./crates/wasm/noir-script
run: |
nargo_binary=${{ github.workspace }}/nargo/nargo
chmod +x $nargo_binary
$nargo_binary compile
- name: Install dependencies
working-directory: ./crates/wasm
run: yarn install

- name: Install playwright deps
working-directory: ./crates/wasm
run: |
npx playwright install
npx playwright install-deps
- name: Run tests
working-directory: ./crates/wasm
run: yarn test:browser
8 changes: 8 additions & 0 deletions crates/wasm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Yarn
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
7 changes: 7 additions & 0 deletions crates/wasm/.mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extension": [
"ts"
],
"spec": "test/node/**/*.test.ts",
"require": "ts-node/register"
}
873 changes: 873 additions & 0 deletions crates/wasm/.yarn/releases/yarn-3.5.1.cjs

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions crates/wasm/noir-script/Nargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name="noir_wasm_testing"
type="bin"
authors = [""]
compiler_version = "0.1"

[dependencies]
3 changes: 3 additions & 0 deletions crates/wasm/noir-script/src/main.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main(x : u64, y : pub u64) {
assert(x < y);
}
29 changes: 23 additions & 6 deletions crates/wasm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@
"The Noir Team <team@noir-lang.org>"
],
"version": "0.9.0",
"license": "MIT",
"main": "./nodejs/noir_wasm.js",
"types": "./web/noir_wasm.d.ts",
"module": "./web/noir_wasm.js",
"files": [
"nodejs",
"web",
"package.json"
],
"main": "./nodejs/noir_wasm.js",
"types": "./web/noir_wasm.d.ts",
"module": "./web/noir_wasm.js",
"sideEffects": false,
"peerDependencies": {
"@noir-lang/noir-source-resolver": "1.1.3"
},
"packageManager": "yarn@3.5.1",
"repository": {
"type": "git",
"url": "https://github.com/noir-lang/noir_wasm.git"
},
"scripts": {
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha",
"test:browser": "web-test-runner"
},
"peerDependencies": {
"@noir-lang/noir-source-resolver": "1.1.2"
},
"devDependencies": {
"@esm-bundle/chai": "^4.3.4-fix.0",
"@noir-lang/noir-source-resolver": "1.1.2",
"@web/dev-server-esbuild": "^0.3.6",
"@web/test-runner": "^0.15.3",
"@web/test-runner-playwright": "^0.10.0",
"chai": "^4.3.7",
"mocha": "^10.2.0",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
}
}
35 changes: 35 additions & 0 deletions crates/wasm/test/browser/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect } from "@esm-bundle/chai";
import initNoirWasm from "../../dist";
import { compileNoirSource, nargoArtifactPath, noirSourcePath } from "../shared";

beforeEach(async () => {
await initNoirWasm();
});

async function getFileContent(path: string): Promise<string> {
const mainnrSourceURL = new URL(path, import.meta.url);
const response = await fetch(mainnrSourceURL);
return await response.text();
}

async function getSource(): Promise<string> {
return getFileContent(noirSourcePath)
}

async function getPrecompiledSource(): Promise<string> {
const compiledData = await getFileContent(nargoArtifactPath);
return JSON.parse(compiledData).bytecode;
}

describe("noir wasm compilation", () => {
it("matches nargos compilation", async () => {
const source = await getSource();

const wasmCircuitBase64 = await compileNoirSource(source);

const cliCircuitBase64 = await getPrecompiledSource();


expect(wasmCircuitBase64).to.equal(cliCircuitBase64);
}).timeout(10e3);
});
1 change: 1 addition & 0 deletions crates/wasm/test/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module '@noir-lang/noir-source-resolver';
34 changes: 34 additions & 0 deletions crates/wasm/test/node/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect } from "@esm-bundle/chai";
import { compileNoirSource, nargoArtifactPath, noirSourcePath } from "../shared";
import { readFileSync } from "node:fs";

async function getFileContent(path: string): Promise<string> {
return readFileSync(path).toString()
}

async function getSource(): Promise<string> {
return getFileContent(noirSourcePath)
}

async function getPrecompiledSource(): Promise<string> {
const compiledData = await getFileContent(nargoArtifactPath);
return JSON.parse(compiledData).bytecode;
}

describe("noir wasm compilation", () => {
it("matches nargos compilation", async () => {
const source = await getSource();

const wasmCircuitBase64 = await compileNoirSource(source);

const cliCircuitBase64 = await getPrecompiledSource();

console.log("wasm", wasmCircuitBase64);

console.log("cli", cliCircuitBase64);

console.log("Compilation is a match? ", wasmCircuitBase64 === cliCircuitBase64);

expect(wasmCircuitBase64).to.equal(cliCircuitBase64);
}).timeout(10e3);
});
31 changes: 31 additions & 0 deletions crates/wasm/test/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { initialiseResolver } from "@noir-lang/noir-source-resolver";
import { compile } from "../dist/";

export const noirSourcePath = "../../noir-script/src/main.nr";
export const nargoArtifactPath = "../../noir-script/target/noir_wasm_testing.json";

export async function compileNoirSource(noir_source: string): Promise<any> {
console.log("Compiling Noir source...");

initialiseResolver((id: string) => {
console.log(`Resolving source ${id}`);

const source = noir_source;

if (typeof source === "undefined") {
throw Error(`Could not resolve source for '${id}'`);
} else {
return source;
}
});

try {
const compiled_noir = compile({});

console.log("Noir source compilation done.");

return compiled_noir.circuit;
} catch (e) {
console.log("Error while compiling:", e);
}
}
17 changes: 17 additions & 0 deletions crates/wasm/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"moduleResolution": "node",
"outDir": "lib",
"target": "ESNext",
"module": "ESNext",
"strict": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"noImplicitAny": true,
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": true,
"resolveJsonModule": true,
"importHelpers": true
}
}
23 changes: 23 additions & 0 deletions crates/wasm/web-test-runner.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { esbuildPlugin } from "@web/dev-server-esbuild";
import { playwrightLauncher } from "@web/test-runner-playwright";

export default {
browsers: [
playwrightLauncher({ product: "chromium" }),
playwrightLauncher({ product: "webkit" }),
playwrightLauncher({ product: "firefox" }),
],
plugins: [
esbuildPlugin({
ts: true,
}),
],
files: ["test/browser/**/*.test.ts"],
nodeResolve: true,
testFramework: {
config: {
ui: "bdd",
timeout: 40000,
},
},
};
Loading

0 comments on commit 08683e1

Please sign in to comment.