@ethproofs/openvm2-wasm-stark-verifier 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ethproofs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # OpenVM v2 Wasm Stark Verifier
2
+
3
+ WebAssembly bindings for the OpenVM v2 STARK verifier.
4
+
5
+ ## Overview
6
+
7
+ This module builds the `verify_vm_stark_proof_decoded` function from the OpenVM v2 `openvm-verify-stark-host` library into WebAssembly, enabling STARK proof verification to run directly in both web browsers and Node.js environments.
8
+
9
+ This is the v2 counterpart of [openvm-wasm-stark-verifier](https://github.com/ethproofs/openvm-wasm-stark-verifier), updated to work with the OpenVM v2 proof format from [openvm-eth](https://github.com/axiom-crypto/openvm-eth/tree/develop-v2.0.0-rc.1).
10
+
11
+ ## Usage
12
+
13
+ ### Installation
14
+
15
+ ```bash
16
+ npm install @ethproofs/openvm2-wasm-stark-verifier
17
+ ```
18
+
19
+ ### React Integration
20
+
21
+ ```typescript
22
+ import init, {
23
+ main,
24
+ verify_stark,
25
+ } from '@ethproofs/openvm2-wasm-stark-verifier';
26
+
27
+ await init(); // Initialize WASM (if needed)
28
+ main(); // Initialize panic hook
29
+
30
+ // Verify a proof (supports both raw and zstd-compressed proofs)
31
+ const isValid = verify_stark(proofBytes, vkBytes);
32
+ ```
33
+
34
+ ### Node.js Usage
35
+
36
+ ```javascript
37
+ const { main, verify_stark } = require('@ethproofs/openvm2-wasm-stark-verifier');
38
+
39
+ // The Node.js version initializes automatically
40
+
41
+ main(); // Initialize panic hook
42
+ const result = verify_stark(proofBytes, vkBytes);
43
+ ```
44
+
45
+ ## Proof Format
46
+
47
+ - **Proof bytes**: Serialized `StarkProofWithPublicValue<F>` in bincode v1 format, optionally zstd-compressed
48
+ - **VK bytes**: Serialized `VmStarkVerifyingKey` in bitcode format
49
+
50
+ This matches the proof format produced by the [openvm-eth reth-benchmark](https://github.com/axiom-crypto/openvm-eth) tooling.
51
+
52
+ ## Testing
53
+
54
+ ### Installation
55
+
56
+ ```bash
57
+ npm install
58
+ ```
59
+
60
+ ### Prerequisites
61
+
62
+ - [Rust](https://www.rust-lang.org/tools/install)
63
+ - [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/)
64
+
65
+ ### Building
66
+
67
+ ```bash
68
+ # Build for all targets
69
+ npm run build:all
70
+ ```
71
+
72
+ ### Node.js Example
73
+
74
+ ```bash
75
+ npm run test:node
76
+ ```
77
+
78
+ This runs the Node.js example that loads proof and verification key files from the filesystem and verifies them.
79
+
80
+ ### Browser Example
81
+
82
+ ```bash
83
+ npm run test
84
+ ```
85
+
86
+ This starts a local HTTP server at `http://localhost:8080` with a browser example that demonstrates:
87
+
88
+ - Loading the WASM module in a browser environment
89
+ - File upload interface for proof and verification key files
90
+ - Interactive STARK proof verification
91
+ - Performance metrics and detailed logging
92
+ - Error handling and user feedback
93
+
94
+ **Note:** The browser example requires files to be served over HTTP due to WASM CORS restrictions. The included server script handles this automatically.
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@ethproofs/openvm2-wasm-stark-verifier",
3
+ "version": "0.1.0",
4
+ "description": "WASM wrapper for OpenVM v2 STARK verifier - verify OpenVM v2 proofs in browsers and Node.js",
5
+ "type": "module",
6
+ "main": "pkg/openvm2_wasm_stark_verifier.js",
7
+ "module": "pkg/openvm2_wasm_stark_verifier.js",
8
+ "types": "pkg/openvm2_wasm_stark_verifier.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./pkg/openvm2_wasm_stark_verifier.d.ts",
12
+ "import": "./pkg/openvm2_wasm_stark_verifier.js",
13
+ "require": "./pkg/openvm2_wasm_stark_verifier.js"
14
+ },
15
+ "./pkg/*": "./pkg/*"
16
+ },
17
+ "files": [
18
+ "pkg/",
19
+ "README.md",
20
+ "test-browser.html",
21
+ "test-serve.mjs"
22
+ ],
23
+ "scripts": {
24
+ "build": "wasm-pack build --target bundler --out-dir pkg",
25
+ "build:node": "wasm-pack build --target nodejs --out-dir pkg-node",
26
+ "build:web": "wasm-pack build --target web --out-dir pkg-web",
27
+ "build:all": "npm run build && npm run build:node && npm run build:web",
28
+ "test": "npm run build && node test-serve.mjs",
29
+ "test:node": "npm run build:node && node test-node.mjs"
30
+ },
31
+ "keywords": [
32
+ "wasm",
33
+ "webassembly",
34
+ "stark",
35
+ "verifier",
36
+ "openvm",
37
+ "zero-knowledge",
38
+ "zk",
39
+ "proof",
40
+ "blockchain",
41
+ "cryptography",
42
+ "vm"
43
+ ],
44
+ "author": "Ethproofs",
45
+ "license": "MIT",
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/ethproofs/openvm2-wasm-stark-verifier"
49
+ },
50
+ "homepage": "https://github.com/ethproofs/openvm2-wasm-stark-verifier#readme",
51
+ "bugs": {
52
+ "url": "https://github.com/ethproofs/openvm2-wasm-stark-verifier/issues"
53
+ },
54
+ "engines": {
55
+ "node": ">=16.0.0"
56
+ },
57
+ "publishConfig": {
58
+ "access": "public"
59
+ },
60
+ "devDependencies": {
61
+ "wasm-pack": "^0.0.0"
62
+ }
63
+ }
package/pkg/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # OpenVM v2 Wasm Stark Verifier
2
+
3
+ WebAssembly bindings for the OpenVM v2 STARK verifier.
4
+
5
+ ## Overview
6
+
7
+ This module builds the `verify_vm_stark_proof_decoded` function from the OpenVM v2 `openvm-verify-stark-host` library into WebAssembly, enabling STARK proof verification to run directly in both web browsers and Node.js environments.
8
+
9
+ This is the v2 counterpart of [openvm-wasm-stark-verifier](https://github.com/ethproofs/openvm-wasm-stark-verifier), updated to work with the OpenVM v2 proof format from [openvm-eth](https://github.com/axiom-crypto/openvm-eth/tree/develop-v2.0.0-rc.1).
10
+
11
+ ## Usage
12
+
13
+ ### Installation
14
+
15
+ ```bash
16
+ npm install @ethproofs/openvm2-wasm-stark-verifier
17
+ ```
18
+
19
+ ### React Integration
20
+
21
+ ```typescript
22
+ import init, {
23
+ main,
24
+ verify_stark,
25
+ } from '@ethproofs/openvm2-wasm-stark-verifier';
26
+
27
+ await init(); // Initialize WASM (if needed)
28
+ main(); // Initialize panic hook
29
+
30
+ // Verify a proof (supports both raw and zstd-compressed proofs)
31
+ const isValid = verify_stark(proofBytes, vkBytes);
32
+ ```
33
+
34
+ ### Node.js Usage
35
+
36
+ ```javascript
37
+ const { main, verify_stark } = require('@ethproofs/openvm2-wasm-stark-verifier');
38
+
39
+ // The Node.js version initializes automatically
40
+
41
+ main(); // Initialize panic hook
42
+ const result = verify_stark(proofBytes, vkBytes);
43
+ ```
44
+
45
+ ## Proof Format
46
+
47
+ - **Proof bytes**: Serialized `StarkProofWithPublicValue<F>` in bincode v1 format, optionally zstd-compressed
48
+ - **VK bytes**: Serialized `VmStarkVerifyingKey` in bitcode format
49
+
50
+ This matches the proof format produced by the [openvm-eth reth-benchmark](https://github.com/axiom-crypto/openvm-eth) tooling.
51
+
52
+ ## Testing
53
+
54
+ ### Installation
55
+
56
+ ```bash
57
+ npm install
58
+ ```
59
+
60
+ ### Prerequisites
61
+
62
+ - [Rust](https://www.rust-lang.org/tools/install)
63
+ - [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/)
64
+
65
+ ### Building
66
+
67
+ ```bash
68
+ # Build for all targets
69
+ npm run build:all
70
+ ```
71
+
72
+ ### Node.js Example
73
+
74
+ ```bash
75
+ npm run test:node
76
+ ```
77
+
78
+ This runs the Node.js example that loads proof and verification key files from the filesystem and verifies them.
79
+
80
+ ### Browser Example
81
+
82
+ ```bash
83
+ npm run test
84
+ ```
85
+
86
+ This starts a local HTTP server at `http://localhost:8080` with a browser example that demonstrates:
87
+
88
+ - Loading the WASM module in a browser environment
89
+ - File upload interface for proof and verification key files
90
+ - Interactive STARK proof verification
91
+ - Performance metrics and detailed logging
92
+ - Error handling and user feedback
93
+
94
+ **Note:** The browser example requires files to be served over HTTP due to WASM CORS restrictions. The included server script handles this automatically.
@@ -0,0 +1,16 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export function main(): void;
5
+
6
+ /**
7
+ * Verify an OpenVM v2 STARK proof
8
+ *
9
+ * # Arguments
10
+ * * `proof_bytes` - The serialized proof data (zstd-compressed, custom codec format)
11
+ * * `vk_bytes` - The serialized verification key (bitcode format)
12
+ *
13
+ * # Returns
14
+ * * `Result<bool, JsValue>` - Ok(true) if proof is valid, Ok(false) if invalid, Err for errors
15
+ */
16
+ export function verify_stark(proof_bytes: Uint8Array, vk_bytes: Uint8Array): boolean;
@@ -0,0 +1,9 @@
1
+ /* @ts-self-types="./openvm2_wasm_stark_verifier.d.ts" */
2
+
3
+ import * as wasm from "./openvm2_wasm_stark_verifier_bg.wasm";
4
+ import { __wbg_set_wasm } from "./openvm2_wasm_stark_verifier_bg.js";
5
+ __wbg_set_wasm(wasm);
6
+ wasm.__wbindgen_start();
7
+ export {
8
+ main, verify_stark
9
+ } from "./openvm2_wasm_stark_verifier_bg.js";
@@ -0,0 +1,175 @@
1
+ export function main() {
2
+ wasm.main();
3
+ }
4
+
5
+ /**
6
+ * Verify an OpenVM v2 STARK proof
7
+ *
8
+ * # Arguments
9
+ * * `proof_bytes` - The serialized proof data (zstd-compressed, custom codec format)
10
+ * * `vk_bytes` - The serialized verification key (bitcode format)
11
+ *
12
+ * # Returns
13
+ * * `Result<bool, JsValue>` - Ok(true) if proof is valid, Ok(false) if invalid, Err for errors
14
+ * @param {Uint8Array} proof_bytes
15
+ * @param {Uint8Array} vk_bytes
16
+ * @returns {boolean}
17
+ */
18
+ export function verify_stark(proof_bytes, vk_bytes) {
19
+ const ptr0 = passArray8ToWasm0(proof_bytes, wasm.__wbindgen_malloc);
20
+ const len0 = WASM_VECTOR_LEN;
21
+ const ptr1 = passArray8ToWasm0(vk_bytes, wasm.__wbindgen_malloc);
22
+ const len1 = WASM_VECTOR_LEN;
23
+ const ret = wasm.verify_stark(ptr0, len0, ptr1, len1);
24
+ if (ret[2]) {
25
+ throw takeFromExternrefTable0(ret[1]);
26
+ }
27
+ return ret[0] !== 0;
28
+ }
29
+ export function __wbg___wbindgen_throw_81fc77679af83bc6(arg0, arg1) {
30
+ throw new Error(getStringFromWasm0(arg0, arg1));
31
+ }
32
+ export function __wbg_error_a6fa202b58aa1cd3(arg0, arg1) {
33
+ let deferred0_0;
34
+ let deferred0_1;
35
+ try {
36
+ deferred0_0 = arg0;
37
+ deferred0_1 = arg1;
38
+ console.error(getStringFromWasm0(arg0, arg1));
39
+ } finally {
40
+ wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
41
+ }
42
+ }
43
+ export function __wbg_log_9ea0fc1d68ddc809(arg0, arg1) {
44
+ console.log(getStringFromWasm0(arg0, arg1));
45
+ }
46
+ export function __wbg_new_227d7c05414eb861() {
47
+ const ret = new Error();
48
+ return ret;
49
+ }
50
+ export function __wbg_stack_3b0d974bbf31e44f(arg0, arg1) {
51
+ const ret = arg1.stack;
52
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
53
+ const len1 = WASM_VECTOR_LEN;
54
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
55
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
56
+ }
57
+ export function __wbindgen_cast_0000000000000001(arg0, arg1) {
58
+ // Cast intrinsic for `Ref(String) -> Externref`.
59
+ const ret = getStringFromWasm0(arg0, arg1);
60
+ return ret;
61
+ }
62
+ export function __wbindgen_init_externref_table() {
63
+ const table = wasm.__wbindgen_externrefs;
64
+ const offset = table.grow(4);
65
+ table.set(0, undefined);
66
+ table.set(offset + 0, undefined);
67
+ table.set(offset + 1, null);
68
+ table.set(offset + 2, true);
69
+ table.set(offset + 3, false);
70
+ }
71
+ let cachedDataViewMemory0 = null;
72
+ function getDataViewMemory0() {
73
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
74
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
75
+ }
76
+ return cachedDataViewMemory0;
77
+ }
78
+
79
+ function getStringFromWasm0(ptr, len) {
80
+ ptr = ptr >>> 0;
81
+ return decodeText(ptr, len);
82
+ }
83
+
84
+ let cachedUint8ArrayMemory0 = null;
85
+ function getUint8ArrayMemory0() {
86
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
87
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
88
+ }
89
+ return cachedUint8ArrayMemory0;
90
+ }
91
+
92
+ function passArray8ToWasm0(arg, malloc) {
93
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
94
+ getUint8ArrayMemory0().set(arg, ptr / 1);
95
+ WASM_VECTOR_LEN = arg.length;
96
+ return ptr;
97
+ }
98
+
99
+ function passStringToWasm0(arg, malloc, realloc) {
100
+ if (realloc === undefined) {
101
+ const buf = cachedTextEncoder.encode(arg);
102
+ const ptr = malloc(buf.length, 1) >>> 0;
103
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
104
+ WASM_VECTOR_LEN = buf.length;
105
+ return ptr;
106
+ }
107
+
108
+ let len = arg.length;
109
+ let ptr = malloc(len, 1) >>> 0;
110
+
111
+ const mem = getUint8ArrayMemory0();
112
+
113
+ let offset = 0;
114
+
115
+ for (; offset < len; offset++) {
116
+ const code = arg.charCodeAt(offset);
117
+ if (code > 0x7F) break;
118
+ mem[ptr + offset] = code;
119
+ }
120
+ if (offset !== len) {
121
+ if (offset !== 0) {
122
+ arg = arg.slice(offset);
123
+ }
124
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
125
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
126
+ const ret = cachedTextEncoder.encodeInto(arg, view);
127
+
128
+ offset += ret.written;
129
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
130
+ }
131
+
132
+ WASM_VECTOR_LEN = offset;
133
+ return ptr;
134
+ }
135
+
136
+ function takeFromExternrefTable0(idx) {
137
+ const value = wasm.__wbindgen_externrefs.get(idx);
138
+ wasm.__externref_table_dealloc(idx);
139
+ return value;
140
+ }
141
+
142
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
143
+ cachedTextDecoder.decode();
144
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
145
+ let numBytesDecoded = 0;
146
+ function decodeText(ptr, len) {
147
+ numBytesDecoded += len;
148
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
149
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
150
+ cachedTextDecoder.decode();
151
+ numBytesDecoded = len;
152
+ }
153
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
154
+ }
155
+
156
+ const cachedTextEncoder = new TextEncoder();
157
+
158
+ if (!('encodeInto' in cachedTextEncoder)) {
159
+ cachedTextEncoder.encodeInto = function (arg, view) {
160
+ const buf = cachedTextEncoder.encode(arg);
161
+ view.set(buf);
162
+ return {
163
+ read: arg.length,
164
+ written: buf.length
165
+ };
166
+ };
167
+ }
168
+
169
+ let WASM_VECTOR_LEN = 0;
170
+
171
+
172
+ let wasm;
173
+ export function __wbg_set_wasm(val) {
174
+ wasm = val;
175
+ }
@@ -0,0 +1,19 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const main: () => void;
5
+ export const verify_stark: (a: number, b: number, c: number, d: number) => [number, number, number];
6
+ export const rust_zstd_wasm_shim_calloc: (a: number, b: number) => number;
7
+ export const rust_zstd_wasm_shim_free: (a: number) => void;
8
+ export const rust_zstd_wasm_shim_malloc: (a: number) => number;
9
+ export const rust_zstd_wasm_shim_memcmp: (a: number, b: number, c: number) => number;
10
+ export const rust_zstd_wasm_shim_memcpy: (a: number, b: number, c: number) => number;
11
+ export const rust_zstd_wasm_shim_memmove: (a: number, b: number, c: number) => number;
12
+ export const rust_zstd_wasm_shim_memset: (a: number, b: number, c: number) => number;
13
+ export const rust_zstd_wasm_shim_qsort: (a: number, b: number, c: number, d: number) => void;
14
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
15
+ export const __wbindgen_malloc: (a: number, b: number) => number;
16
+ export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
17
+ export const __wbindgen_externrefs: WebAssembly.Table;
18
+ export const __externref_table_dealloc: (a: number) => void;
19
+ export const __wbindgen_start: () => void;
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "openvm2-wasm-stark-verifier",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "files": [
6
+ "openvm2_wasm_stark_verifier_bg.wasm",
7
+ "openvm2_wasm_stark_verifier.js",
8
+ "openvm2_wasm_stark_verifier_bg.js",
9
+ "openvm2_wasm_stark_verifier.d.ts"
10
+ ],
11
+ "main": "openvm2_wasm_stark_verifier.js",
12
+ "types": "openvm2_wasm_stark_verifier.d.ts",
13
+ "sideEffects": [
14
+ "./openvm2_wasm_stark_verifier.js",
15
+ "./snippets/*"
16
+ ]
17
+ }
@@ -0,0 +1,337 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>OpenVM v2 WASM STARK Verifier - Browser Example</title>
7
+ <style>
8
+ body {
9
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
10
+ max-width: 800px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ background-color: #1a1a1a;
14
+ color: #e0e0e0;
15
+ line-height: 1.6;
16
+ }
17
+
18
+ .container {
19
+ background-color: #2d2d2d;
20
+ border-radius: 8px;
21
+ padding: 20px;
22
+ margin-bottom: 20px;
23
+ box-shadow: 0 2px 10px rgba(0,0,0,0.3);
24
+ }
25
+
26
+ h1 {
27
+ color: #4CAF50;
28
+ text-align: center;
29
+ margin-bottom: 30px;
30
+ }
31
+
32
+ h2 {
33
+ color: #81C784;
34
+ border-bottom: 2px solid #4CAF50;
35
+ padding-bottom: 5px;
36
+ }
37
+
38
+ .status {
39
+ padding: 10px;
40
+ border-radius: 4px;
41
+ margin: 10px 0;
42
+ font-weight: bold;
43
+ }
44
+
45
+ .status.loading {
46
+ background-color: #FFF3E0;
47
+ color: #FF8F00;
48
+ border: 1px solid #FFB74D;
49
+ }
50
+
51
+ .status.success {
52
+ background-color: #E8F5E8;
53
+ color: #2E7D32;
54
+ border: 1px solid #4CAF50;
55
+ }
56
+
57
+ .status.error {
58
+ background-color: #FFEBEE;
59
+ color: #C62828;
60
+ border: 1px solid #F44336;
61
+ }
62
+
63
+ .file-info {
64
+ background-color: #424242;
65
+ padding: 10px;
66
+ border-radius: 4px;
67
+ margin: 10px 0;
68
+ font-family: monospace;
69
+ }
70
+
71
+ button {
72
+ background-color: #4CAF50;
73
+ color: white;
74
+ padding: 10px 20px;
75
+ border: none;
76
+ border-radius: 4px;
77
+ cursor: pointer;
78
+ font-size: 16px;
79
+ margin: 10px 5px;
80
+ }
81
+
82
+ button:hover {
83
+ background-color: #45a049;
84
+ }
85
+
86
+ button:disabled {
87
+ background-color: #666;
88
+ cursor: not-allowed;
89
+ }
90
+
91
+ .file-input {
92
+ margin: 10px 0;
93
+ }
94
+
95
+ input[type="file"] {
96
+ background-color: #424242;
97
+ color: #e0e0e0;
98
+ padding: 5px;
99
+ border: 1px solid #666;
100
+ border-radius: 4px;
101
+ }
102
+
103
+ .log {
104
+ background-color: #1e1e1e;
105
+ border: 1px solid #444;
106
+ border-radius: 4px;
107
+ padding: 15px;
108
+ margin: 15px 0;
109
+ font-family: monospace;
110
+ font-size: 12px;
111
+ white-space: pre-wrap;
112
+ max-height: 300px;
113
+ overflow-y: auto;
114
+ }
115
+
116
+ .performance {
117
+ background-color: #263238;
118
+ padding: 10px;
119
+ border-radius: 4px;
120
+ margin: 10px 0;
121
+ }
122
+
123
+ .result {
124
+ font-size: 18px;
125
+ font-weight: bold;
126
+ padding: 15px;
127
+ border-radius: 4px;
128
+ margin: 15px 0;
129
+ text-align: center;
130
+ }
131
+
132
+ .result.valid {
133
+ background-color: #1B5E20;
134
+ color: #4CAF50;
135
+ border: 2px solid #4CAF50;
136
+ }
137
+
138
+ .result.invalid {
139
+ background-color: #B71C1C;
140
+ color: #F44336;
141
+ border: 2px solid #F44336;
142
+ }
143
+ </style>
144
+ </head>
145
+ <body>
146
+ <h1>OpenVM v2 WASM STARK Verifier</h1>
147
+
148
+ <div class="container">
149
+ <h2>Browser Integration Example</h2>
150
+ <p>This example demonstrates how to use the OpenVM v2 WASM STARK verifier in a web browser environment.</p>
151
+
152
+ <div id="wasmStatus" class="status loading">Loading WASM module...</div>
153
+ </div>
154
+
155
+ <div class="container">
156
+ <h2>File Selection</h2>
157
+ <p>Select the proof and verification key files to test verification:</p>
158
+
159
+ <div class="file-input">
160
+ <label for="proofFile"><strong>Proof file (.bin):</strong></label><br>
161
+ <input type="file" id="proofFile" accept=".bin" />
162
+ <div id="proofInfo" class="file-info" style="display: none;"></div>
163
+ </div>
164
+
165
+ <div class="file-input">
166
+ <label for="vkFile"><strong>Verification Key file (.bin):</strong></label><br>
167
+ <input type="file" id="vkFile" accept=".bin" />
168
+ <div id="vkInfo" class="file-info" style="display: none;"></div>
169
+ </div>
170
+ </div>
171
+
172
+ <div class="container">
173
+ <h2>Verification</h2>
174
+ <button id="verifyBtn" disabled onclick="runVerification()">Run Verification</button>
175
+ <button id="clearLogBtn" onclick="clearLog()">Clear Log</button>
176
+
177
+ <div id="result" class="result" style="display: none;"></div>
178
+ <div id="performance" class="performance" style="display: none;"></div>
179
+ </div>
180
+
181
+ <div class="container">
182
+ <h2>Console Output</h2>
183
+ <div id="log" class="log"></div>
184
+ </div>
185
+
186
+ <script type="module">
187
+ import init, { main, verify_stark } from './pkg-web/openvm2_wasm_stark_verifier.js';
188
+
189
+ let wasmModule = null;
190
+ let proofBytes = null;
191
+ let vkBytes = null;
192
+
193
+ function log(message) {
194
+ const logElement = document.getElementById('log');
195
+ const timestamp = new Date().toLocaleTimeString();
196
+ logElement.textContent += `[${timestamp}] ${message}\n`;
197
+ logElement.scrollTop = logElement.scrollHeight;
198
+ console.log(message);
199
+ }
200
+
201
+ function clearLog() {
202
+ document.getElementById('log').textContent = '';
203
+ }
204
+
205
+ function updateStatus(elementId, message, className) {
206
+ const element = document.getElementById(elementId);
207
+ element.textContent = message;
208
+ element.className = `status ${className}`;
209
+ }
210
+
211
+ function updateFileInfo(elementId, file) {
212
+ const element = document.getElementById(elementId);
213
+ element.style.display = 'block';
214
+ element.innerHTML = `
215
+ <strong>File:</strong> ${file.name}<br>
216
+ <strong>Size:</strong> ${file.size.toLocaleString()} bytes<br>
217
+ <strong>Type:</strong> ${file.type || 'binary'}
218
+ `;
219
+ }
220
+
221
+ function checkCanVerify() {
222
+ const canVerify = wasmModule && proofBytes && vkBytes;
223
+ document.getElementById('verifyBtn').disabled = !canVerify;
224
+ return canVerify;
225
+ }
226
+
227
+ async function initializeWasm() {
228
+ try {
229
+ log('Initializing WASM module...');
230
+ wasmModule = await init();
231
+ log('WASM module loaded, initializing panic hook...');
232
+ main();
233
+ updateStatus('wasmStatus', 'WASM module loaded successfully', 'success');
234
+ log('WASM module initialized successfully');
235
+ checkCanVerify();
236
+ } catch (error) {
237
+ updateStatus('wasmStatus', `Failed to load WASM module: ${error.message}`, 'error');
238
+ log(`Error initializing WASM: ${error.message}`);
239
+ console.error('WASM initialization error:', error);
240
+ }
241
+ }
242
+
243
+ function readFileAsArrayBuffer(file) {
244
+ return new Promise((resolve, reject) => {
245
+ const reader = new FileReader();
246
+ reader.onload = (e) => resolve(new Uint8Array(e.target.result));
247
+ reader.onerror = (e) => reject(new Error(`Failed to read file: ${e.target.error}`));
248
+ reader.readAsArrayBuffer(file);
249
+ });
250
+ }
251
+
252
+ document.getElementById('proofFile').addEventListener('change', async (e) => {
253
+ const file = e.target.files[0];
254
+ if (file) {
255
+ try {
256
+ log(`Loading proof file: ${file.name}`);
257
+ proofBytes = await readFileAsArrayBuffer(file);
258
+ updateFileInfo('proofInfo', file);
259
+ log(`Proof file loaded: ${proofBytes.length} bytes`);
260
+ checkCanVerify();
261
+ } catch (error) {
262
+ log(`Error loading proof file: ${error.message}`);
263
+ }
264
+ }
265
+ });
266
+
267
+ document.getElementById('vkFile').addEventListener('change', async (e) => {
268
+ const file = e.target.files[0];
269
+ if (file) {
270
+ try {
271
+ log(`Loading verification key file: ${file.name}`);
272
+ vkBytes = await readFileAsArrayBuffer(file);
273
+ updateFileInfo('vkInfo', file);
274
+ log(`Verification key loaded: ${vkBytes.length} bytes`);
275
+ checkCanVerify();
276
+ } catch (error) {
277
+ log(`Error loading verification key file: ${error.message}`);
278
+ }
279
+ }
280
+ });
281
+
282
+ window.runVerification = async function() {
283
+ if (!checkCanVerify()) {
284
+ log('Cannot run verification: missing WASM module, proof, or verification key');
285
+ return;
286
+ }
287
+
288
+ const resultElement = document.getElementById('result');
289
+ const performanceElement = document.getElementById('performance');
290
+
291
+ try {
292
+ log('Starting verification...');
293
+ log(`Proof size: ${proofBytes.length.toLocaleString()} bytes`);
294
+ log(`VK size: ${vkBytes.length.toLocaleString()} bytes`);
295
+
296
+ const startTime = performance.now();
297
+ const result = verify_stark(proofBytes, vkBytes);
298
+ const endTime = performance.now();
299
+ const duration = endTime - startTime;
300
+
301
+ resultElement.style.display = 'block';
302
+ resultElement.className = `result ${result ? 'valid' : 'invalid'}`;
303
+ resultElement.textContent = result ? 'PROOF VALID' : 'PROOF INVALID';
304
+
305
+ performanceElement.style.display = 'block';
306
+ performanceElement.innerHTML = `
307
+ <strong>Performance Metrics:</strong><br>
308
+ Verification time: ${duration.toFixed(2)} milliseconds<br>
309
+ Throughput: ${((proofBytes.length + vkBytes.length) / 1024 / (duration / 1000)).toFixed(2)} KB/s
310
+ `;
311
+
312
+ log(`Verification completed: ${result ? 'VALID' : 'INVALID'}`);
313
+ log(`Time taken: ${duration.toFixed(2)} milliseconds`);
314
+
315
+ } catch (error) {
316
+ resultElement.style.display = 'block';
317
+ resultElement.className = 'result invalid';
318
+ resultElement.textContent = `VERIFICATION ERROR: ${error.message}`;
319
+
320
+ log(`Verification error: ${error.message}`);
321
+ console.error('Verification error:', error);
322
+ }
323
+ };
324
+
325
+ initializeWasm();
326
+
327
+ log('OpenVM v2 WASM STARK Verifier browser example loaded');
328
+ log('Instructions:');
329
+ log(' 1. Wait for WASM module to load');
330
+ log(' 2. Select a proof file (.bin)');
331
+ log(' 3. Select a verification key file (.bin)');
332
+ log(' 4. Click "Run Verification"');
333
+ log('');
334
+ log('Tip: You can use the proof and verification key files from the proofs/ and vks/ directories');
335
+ </script>
336
+ </body>
337
+ </html>
package/test-serve.mjs ADDED
@@ -0,0 +1,118 @@
1
+ import http from 'http';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+
9
+ const PORT = process.env.PORT || 8080;
10
+
11
+ // MIME types for different file extensions
12
+ const mimeTypes = {
13
+ '.html': 'text/html',
14
+ '.js': 'application/javascript',
15
+ '.wasm': 'application/wasm',
16
+ '.json': 'application/json',
17
+ '.bin': 'application/octet-stream',
18
+ '.css': 'text/css',
19
+ '.ts': 'application/typescript',
20
+ };
21
+
22
+ function getMimeType(filePath) {
23
+ const ext = path.extname(filePath).toLowerCase();
24
+ return mimeTypes[ext] || 'application/octet-stream';
25
+ }
26
+
27
+ function serveFile(res, filePath) {
28
+ const fullPath = path.join(__dirname, filePath);
29
+
30
+ fs.readFile(fullPath, (err, data) => {
31
+ if (err) {
32
+ if (
33
+ !filePath.includes('favicon') &&
34
+ !filePath.includes('ws') &&
35
+ !filePath.includes('socket')
36
+ ) {
37
+ console.error(`File not found: ${filePath}`);
38
+ }
39
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
40
+ res.end('File not found');
41
+ return;
42
+ }
43
+
44
+ const mimeType = getMimeType(filePath);
45
+ const headers = {
46
+ 'Content-Type': mimeType,
47
+ 'Cross-Origin-Embedder-Policy': 'require-corp',
48
+ 'Cross-Origin-Opener-Policy': 'same-origin',
49
+ };
50
+
51
+ if (filePath.endsWith('.wasm')) {
52
+ headers['Content-Type'] = 'application/wasm';
53
+ }
54
+
55
+ res.writeHead(200, headers);
56
+ res.end(data);
57
+
58
+ console.log(`Served: ${filePath} (${mimeType})`);
59
+ });
60
+ }
61
+
62
+ const server = http.createServer((req, res) => {
63
+ let url = req.url;
64
+
65
+ if (url === '/') {
66
+ url = '/test-browser.html';
67
+ }
68
+
69
+ url = decodeURIComponent(url.split('?')[0]);
70
+
71
+ if (url.includes('..')) {
72
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
73
+ res.end('Bad Request');
74
+ return;
75
+ }
76
+
77
+ if (req.url === '/ws' || req.headers.upgrade === 'websocket') {
78
+ res.writeHead(400, { 'Content-Type': 'text/plain' });
79
+ res.end('WebSocket connections not supported by this server');
80
+ return;
81
+ }
82
+
83
+ const filePath = url.startsWith('/') ? url.slice(1) : url;
84
+
85
+ console.log(`Request: ${req.method} ${req.url} -> ${filePath}`);
86
+
87
+ serveFile(res, filePath);
88
+ });
89
+
90
+ server.listen(PORT, () => {
91
+ console.log('OpenVM v2 WASM STARK Verifier Example Server');
92
+ console.log(`Server running at http://localhost:${PORT}`);
93
+ console.log('');
94
+ console.log('Available endpoints:');
95
+ console.log(
96
+ ` http://localhost:${PORT}/ - Browser example`
97
+ );
98
+ console.log(
99
+ ` http://localhost:${PORT}/pkg/ - WASM package files`
100
+ );
101
+ console.log(` http://localhost:${PORT}/proofs/ - Proof files`);
102
+ console.log(
103
+ ` http://localhost:${PORT}/vks/ - Verification keys`
104
+ );
105
+ console.log('');
106
+ console.log(
107
+ 'Open your browser and navigate to the server URL to test the WASM verifier!'
108
+ );
109
+ console.log('Press Ctrl+C to stop the server');
110
+ });
111
+
112
+ process.on('SIGINT', () => {
113
+ console.log('\nShutting down server...');
114
+ server.close(() => {
115
+ console.log('Server shut down gracefully');
116
+ process.exit(0);
117
+ });
118
+ });