Skip to main content
Version: 0.1.0

Web(Wasm) setup

This tutorial will show you how to build static library for web browser.

Before proceeding, ensure that Rust, Wasm-Pack and Chrome are installed. Refer to the Prerequisites.

Support Halo2 Circuit Implementation

This section assumes the existence of a user-defined circuit implementation based on the PSE Halo2.

Note that there are multiple Halo2 implementations (e.g., Zcash, PSE, Axiom). Mopro primarily supports the PSE Halo2, which is a Plonk backend and works well with wasm-bindgen-rayon. Refer to the README of mopro-wasm for information about compatibility between Halo2 and Wasm.

Update "mopro-wasm-lib"

Once followed "3. Mopro build" for Web(Wasm) in "Getting Started" page, there is "mopro-wasm-lib" would be generated when it selected with web template.

The "mopro-wasm-lib" is the place that compile wasm code eventually. So, it should be updated users Halo2 circuit instead of the example circuit implementations: fibonacci circuit with different backends: "plonk", "hyperplonk" and "gemini".

1. Modify 'Cargo.toml' in the "mopro-wasm-lib"

The user-defined circuit implmentation crate should be added as a dependency manually, as illustrated below:

[package]
name = "mopro-wasm-lib"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["rlib", "cdylib"]

[dependencies]
// mopro-wasm = { git = "https://github.com/zkmopro/mopro",features = [
// "gemini",
// "hyperplonk",
// "plonk",
// ]}
my-halo2-circuit = { git = "http://github.com/users/my-halo2-circuit.git" }

[target.wasm32-unknown-unknown.dependencies]
console_error_panic_hook = "0.1.7"
getrandom = { version = "0.2.15", features = ["js"] }
serde-wasm-bindgen = "0.6.5"
wasm-bindgen = { version = "0.2.95", features = ["serde-serialize"] }
wasm-bindgen-console-logger = "0.1.1"
wasm-bindgen-futures = "0.4.47"
wasm-bindgen-rayon = { version = "1.2.2", features = ["no-bundler"] }
wasm-bindgen-test = "0.3.42"

The mopro-wasm crate no longer required for compiling users-defined circuit implementation: "my-halo2-circuit" in that case.

2. Create Wrapper Functions for Generate/Verify proof method

To compile Wasm code with the circuit, wrapper functions for generating and verifying proof methods in the user-defined circuit implementation must be created in mopro-wasm-lib/src/lib.rs, using the example structure provided below:

use my_halo2_circuit;

#[wasm_bindgen]
pub fn generate_proof(input: JsValue) -> Result<JsValue, JsValue> {
// function implementations with `my-halo2-circuit`
let proof = my_halo2_circuit::generate_proof(parsed_input);
to_value(...)
}

#[wasm_bindgen]
pub fn verify_proof(proof: JsValue, public_inputs: JsValue) -> Result<JsValue, JsValue> {
// function implementations with `my-halo2-circuit`
let result = my_halo2_circuit::verify_proof(parsed_proof, parsed_public_input);
to_value(...)
}

3. Build again for web

To ensure a clean build, remove the existing MoproWasmBindings directory in the mopro-example-app, which was previously generated with mopro-wasm-lib. Then, execute the mopro build command again, selecting the "web" platform in mopro-example-app:

mopro-example-app $ rm -rf MoproWasmBindings
mopro-example-app $ mopro build

4. Integrate the Wasm Code:

The wasm code can be imported and used in a web application, as illustrated below:

const mopro_wasm = await import('./MoproWasmBindings/mopro_wasm_lib.js');
await mopro_wasm.default();
await mopro_wasm.initThreadPool(navigator.hardwareConcurrency);

async function generateProof (input) {
const proof = await mopro_wasm.generate_proof(input);
console.log(proof);
}

Initializing with initThreadPool is necessary to enable multi-threading n WebAssembly within the browser.

Note that the web template generated using the mopro create command is currently built only for example circuit implementations: plonk-fibonacci, hyperplonk-fibonacci and gemini-fibonacci. User should modify index.js and index.html manually if want to use the web template with users' circuit implementation, such as my-halo2-circuit in this tutorial.