JavaScript and WebAssembly tooling for generating and verifying
dusk-plonk proofs in the browser.
⚠️ DISCLAIMER: this code is experimental, and thus, unstable. Use at your own risk.
- PlonkWasm: a Rust crate with reusable proof, verification, serialization, and wasm ABI helpers.
- PlonkJS: a JavaScript loader that calls the exported wasm proof API.
- integration-tests: a test crate that links a concrete circuit, builds the wasm artifact, and verifies the JavaScript proof flow from Rust.
Run the full test flow:
make testThat command:
- Generates prover and verifier keys for the integration test circuit.
- Builds the test wasm artifact.
- Computes a proof through
plonkjs. - Verifies the serialized proof with the Rust verifier from
dusk-plonk.
Run only the Rust tests:
make test-rustBuild the raw wasm artifact used by Node tests:
make build-wasm-rawRun the browser benchmark/example with wasm Rayon enabled:
make serve-exampleThis builds the raw wasm used by Node tests plus the wasm-bindgen/Rayon browser
artifact, then serves the example with the COOP/COEP headers required by
SharedArrayBuffer and WebAssembly threads.
The threaded wasm build currently expects:
- a nightly Rust toolchain with
rust-src - the
wasm-bindgenCLI onPATH - browser support for
SharedArrayBuffer
The shared-memory maximum defaults to 2 GiB. Override it for larger circuits:
WASM_RAYON_MAX_MEMORY=<bytes> make build-wasm-rayonimport { readFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { loadPlonkJs } from "./plonkjs/src/index.mjs";
const keysPath = "target/integration-test-fixtures/test-keys.json";
const keys = JSON.parse(await readFile(keysPath, "utf8"));
const keysDir = dirname(keysPath);
const [proverKey, verifierKey] = await Promise.all([
readFile(join(keysDir, keys.prover_key_path)),
readFile(join(keysDir, keys.verifier_key_path))
]);
const plonkjs = await loadPlonkJs({
modulePath: new URL("./plonkjs/dist/plonkwasm.js", import.meta.url),
threads: true
});
await plonkjs.init(proverKey, verifierKey);
const { proof, publicInputs } = await plonkjs.prove({
seed: new Uint8Array(32).fill(9),
inputs: {
left: 13,
right: 17
}
});
const verified = await plonkjs.verify(proof, publicInputs);For the integration test wasm, left and right are circuit inputs and the
public input is their product.
This project is licensed under the Mozilla Public License Version 2.0
(MPL-2.0). See LICENSE for the full license text.