@jupitermetalabs/face-zk-sdk 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 +201 -0
- package/README.md +181 -0
- package/assets/README.md +22 -0
- package/assets/face-guidance/face-logic.js.txt +77 -0
- package/assets/face-guidance/index.html +173 -0
- package/assets/face-guidance/pose-guidance.js.txt +403 -0
- package/assets/liveness/antispoof.js.txt +143 -0
- package/assets/liveness/index.html +451 -0
- package/assets/liveness/liveness.js.txt +1003 -0
- package/assets/mediapipe/face_mesh.js.txt +131 -0
- package/assets/mediapipe/face_mesh_solution_packed_assets.data +0 -0
- package/assets/mediapipe/face_mesh_solution_simd_wasm_bin.wasm +0 -0
- package/assets/mediapipe/face_mesh_solution_wasm_bin.wasm +0 -0
- package/assets/onnx/ort-wasm-simd.wasm +0 -0
- package/assets/onnx/ort-wasm.wasm +0 -0
- package/assets/onnx/ort.min.js.txt +7 -0
- package/assets/wasm/zk_face_wasm_bg.wasm +0 -0
- package/assets/zk-worker.html +472 -0
- package/cli/copy-ort-assets.js +65 -0
- package/cli/setup.js +266 -0
- package/dist/FaceZkSdk.d.ts +69 -0
- package/dist/FaceZkSdk.js +132 -0
- package/dist/assets/onnx/ort-min.d.ts +1 -0
- package/dist/assets/onnx/ort-min.js +8 -0
- package/dist/config/defaults.d.ts +49 -0
- package/dist/config/defaults.js +55 -0
- package/dist/config/types.d.ts +123 -0
- package/dist/config/types.js +16 -0
- package/dist/core/enrollment-core.d.ts +68 -0
- package/dist/core/enrollment-core.js +202 -0
- package/dist/core/matching.d.ts +69 -0
- package/dist/core/matching.js +96 -0
- package/dist/core/types.d.ts +365 -0
- package/dist/core/types.js +34 -0
- package/dist/core/verification-core.d.ts +120 -0
- package/dist/core/verification-core.js +434 -0
- package/dist/core/zk-core.d.ts +69 -0
- package/dist/core/zk-core.js +240 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +39 -0
- package/dist/react-native/adapters/faceEmbeddingProvider.d.ts +38 -0
- package/dist/react-native/adapters/faceEmbeddingProvider.js +41 -0
- package/dist/react-native/adapters/imageDataProvider.d.ts +53 -0
- package/dist/react-native/adapters/imageDataProvider.js +97 -0
- package/dist/react-native/adapters/livenessProvider.d.ts +133 -0
- package/dist/react-native/adapters/livenessProvider.js +144 -0
- package/dist/react-native/adapters/zkProofEngine-webview.d.ts +73 -0
- package/dist/react-native/adapters/zkProofEngine-webview.js +129 -0
- package/dist/react-native/components/FacePoseGuidanceWebView.d.ts +30 -0
- package/dist/react-native/components/FacePoseGuidanceWebView.js +474 -0
- package/dist/react-native/components/LivenessWebView.d.ts +39 -0
- package/dist/react-native/components/LivenessWebView.js +348 -0
- package/dist/react-native/components/OnnxRuntimeWebView.d.ts +54 -0
- package/dist/react-native/components/OnnxRuntimeWebView.js +394 -0
- package/dist/react-native/components/ZkProofWebView.d.ts +59 -0
- package/dist/react-native/components/ZkProofWebView.js +259 -0
- package/dist/react-native/dependencies.d.ts +144 -0
- package/dist/react-native/dependencies.js +123 -0
- package/dist/react-native/hooks/useOnnxLoader.d.ts +38 -0
- package/dist/react-native/hooks/useOnnxLoader.js +81 -0
- package/dist/react-native/hooks/useWasmLoader.d.ts +30 -0
- package/dist/react-native/hooks/useWasmLoader.js +122 -0
- package/dist/react-native/index.d.ts +59 -0
- package/dist/react-native/index.js +96 -0
- package/dist/react-native/services/FaceRecognition.d.ts +70 -0
- package/dist/react-native/services/FaceRecognition.js +517 -0
- package/dist/react-native/ui/FaceZkVerificationFlow.d.ts +97 -0
- package/dist/react-native/ui/FaceZkVerificationFlow.js +433 -0
- package/dist/react-native/ui/ReferenceEnrollmentFlow.d.ts +72 -0
- package/dist/react-native/ui/ReferenceEnrollmentFlow.js +321 -0
- package/dist/react-native/utils/faceAlignment.d.ts +37 -0
- package/dist/react-native/utils/faceAlignment.js +182 -0
- package/dist/react-native/utils/modelInitialisationChecks.d.ts +36 -0
- package/dist/react-native/utils/modelInitialisationChecks.js +92 -0
- package/dist/react-native/utils/resolveModelUri.d.ts +55 -0
- package/dist/react-native/utils/resolveModelUri.js +172 -0
- package/dist/react-native/utils/resolveUiConfig.d.ts +41 -0
- package/dist/react-native/utils/resolveUiConfig.js +76 -0
- package/dist/storage/defaultStorageAdapter.d.ts +44 -0
- package/dist/storage/defaultStorageAdapter.js +299 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/face-zk.config.example.js +88 -0
- package/package.json +76 -0
|
Binary file
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>ZK Worker</title>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<div id="status">Initializing...</div>
|
|
11
|
+
<script>
|
|
12
|
+
// ==========================================
|
|
13
|
+
// WASM Bindings (Full set from pkg-web/zk_face_wasm.js)
|
|
14
|
+
// BUILD TIMESTAMP: 2025-12-22T17:00:00 [CACHE_BUST]
|
|
15
|
+
// ==========================================
|
|
16
|
+
const BUILD_TIMESTAMP = "2025-12-22T17:00:00";
|
|
17
|
+
let wasm;
|
|
18
|
+
|
|
19
|
+
const heap = new Array(128).fill(undefined);
|
|
20
|
+
heap.push(undefined, null, true, false);
|
|
21
|
+
|
|
22
|
+
function getObject(idx) { return heap[idx]; }
|
|
23
|
+
|
|
24
|
+
let heap_next = heap.length;
|
|
25
|
+
|
|
26
|
+
function dropObject(idx) {
|
|
27
|
+
if (idx < 132) return;
|
|
28
|
+
heap[idx] = heap_next;
|
|
29
|
+
heap_next = idx;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function takeObject(idx) {
|
|
33
|
+
const ret = getObject(idx);
|
|
34
|
+
dropObject(idx);
|
|
35
|
+
return ret;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
function isLikeNone(x) {
|
|
41
|
+
return x === undefined || x === null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --- Memory Views ---
|
|
45
|
+
let cachedDataViewMemory0 = null;
|
|
46
|
+
function getDataViewMemory0() {
|
|
47
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
48
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
49
|
+
}
|
|
50
|
+
return cachedDataViewMemory0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let cachedUint8ArrayMemory0 = null;
|
|
54
|
+
function getUint8ArrayMemory0() {
|
|
55
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
56
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
57
|
+
}
|
|
58
|
+
return cachedUint8ArrayMemory0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
62
|
+
ptr = ptr >>> 0;
|
|
63
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// --- String Handling ---
|
|
67
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
68
|
+
cachedTextDecoder.decode();
|
|
69
|
+
|
|
70
|
+
function getStringFromWasm0(ptr, len) {
|
|
71
|
+
ptr = ptr >>> 0;
|
|
72
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let WASM_VECTOR_LEN = 0;
|
|
76
|
+
let cachedTextEncoder = new TextEncoder('utf-8');
|
|
77
|
+
|
|
78
|
+
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
|
79
|
+
? function (arg, view) {
|
|
80
|
+
return cachedTextEncoder.encodeInto(arg, view);
|
|
81
|
+
}
|
|
82
|
+
: function (arg, view) {
|
|
83
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
84
|
+
view.set(buf);
|
|
85
|
+
return {
|
|
86
|
+
read: arg.length,
|
|
87
|
+
written: buf.length
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
92
|
+
if (realloc === undefined) {
|
|
93
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
94
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
95
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
96
|
+
WASM_VECTOR_LEN = buf.length;
|
|
97
|
+
return ptr;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let len = arg.length;
|
|
101
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
102
|
+
const mem = getUint8ArrayMemory0();
|
|
103
|
+
let offset = 0;
|
|
104
|
+
|
|
105
|
+
for (; offset < len; offset++) {
|
|
106
|
+
const code = arg.charCodeAt(offset);
|
|
107
|
+
if (code > 0x7F) break;
|
|
108
|
+
mem[ptr + offset] = code;
|
|
109
|
+
}
|
|
110
|
+
if (offset !== len) {
|
|
111
|
+
if (offset !== 0) {
|
|
112
|
+
arg = arg.slice(offset);
|
|
113
|
+
}
|
|
114
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
115
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
116
|
+
const ret = encodeString(arg, view);
|
|
117
|
+
offset += ret.written;
|
|
118
|
+
}
|
|
119
|
+
WASM_VECTOR_LEN = offset;
|
|
120
|
+
return ptr;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
function takeFromExternrefTable0(idx) {
|
|
126
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
127
|
+
wasm.__externref_table_dealloc(idx);
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// --- THE FULL IMPORTS OBJECT ---
|
|
132
|
+
function getImports() {
|
|
133
|
+
const wbg = {};
|
|
134
|
+
|
|
135
|
+
wbg.__wbg_error_7534b8e9a36f1ab4 = function (arg0, arg1) {
|
|
136
|
+
let deferred0_0;
|
|
137
|
+
let deferred0_1;
|
|
138
|
+
try {
|
|
139
|
+
deferred0_0 = arg0;
|
|
140
|
+
deferred0_1 = arg1;
|
|
141
|
+
console.error(getStringFromWasm0(arg0, arg1));
|
|
142
|
+
} finally {
|
|
143
|
+
wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
wbg.__wbg_new_8a6f238a6ece86ea = function () {
|
|
147
|
+
const ret = new Error();
|
|
148
|
+
return ret;
|
|
149
|
+
};
|
|
150
|
+
wbg.__wbg_stack_0ed75d68575b0f3c = function (arg0, arg1) {
|
|
151
|
+
const ret = arg1.stack;
|
|
152
|
+
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
153
|
+
const len1 = WASM_VECTOR_LEN;
|
|
154
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
155
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
156
|
+
};
|
|
157
|
+
wbg.__wbindgen_cast_2241b6af4c4b2941 = function (arg0, arg1) {
|
|
158
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
159
|
+
return ret;
|
|
160
|
+
};
|
|
161
|
+
wbg.__wbindgen_init_externref_table = function () {
|
|
162
|
+
const table = wasm.__wbindgen_externrefs;
|
|
163
|
+
const offset = table.grow(4);
|
|
164
|
+
table.set(0, undefined);
|
|
165
|
+
table.set(offset + 0, undefined);
|
|
166
|
+
table.set(offset + 1, null);
|
|
167
|
+
table.set(offset + 2, true);
|
|
168
|
+
table.set(offset + 3, false);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// DUAL-MODE RETURN
|
|
172
|
+
return {
|
|
173
|
+
wbg: wbg,
|
|
174
|
+
'./zk_face_wasm_bg.js': wbg
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function finalizeInit(instance, module) {
|
|
179
|
+
wasm = instance.exports;
|
|
180
|
+
cachedUint8ArrayMemory0 = null;
|
|
181
|
+
cachedDataViewMemory0 = null;
|
|
182
|
+
|
|
183
|
+
// Critical: Initialize the externref table
|
|
184
|
+
wasm.__wbindgen_start();
|
|
185
|
+
return wasm;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ==========================================
|
|
189
|
+
// Main Application Logic
|
|
190
|
+
// ==========================================
|
|
191
|
+
|
|
192
|
+
function log(msg) {
|
|
193
|
+
console.log(msg);
|
|
194
|
+
if (window.ReactNativeWebView) {
|
|
195
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'log', message: msg }));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function base64ToUint8Array(base64) {
|
|
200
|
+
// Basic Base64 decoding - ensure whitespace is removed
|
|
201
|
+
const cleanBase64 = base64.replace(/\s/g, '');
|
|
202
|
+
const binary_string = window.atob(cleanBase64);
|
|
203
|
+
const len = binary_string.length;
|
|
204
|
+
const bytes = new Uint8Array(len);
|
|
205
|
+
for (let i = 0; i < len; i++) {
|
|
206
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
207
|
+
}
|
|
208
|
+
return bytes;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Initialize WASM (Plonky3 - No Proving Key Needed!)
|
|
212
|
+
async function initWasm(base64Data) {
|
|
213
|
+
try {
|
|
214
|
+
log('[ZK Worker] Instantiating Plonky3 WASM... Build: ' + (typeof BUILD_TIMESTAMP !== 'undefined' ? BUILD_TIMESTAMP : 'UNKNOWN'));
|
|
215
|
+
const bytes = base64ToUint8Array(base64Data);
|
|
216
|
+
|
|
217
|
+
// Use the imports from our inlined glue code
|
|
218
|
+
const imports = getImports();
|
|
219
|
+
log('[ZK Worker] Imports prepared. Keys: ' + Object.keys(imports).join(', '));
|
|
220
|
+
|
|
221
|
+
const { instance, module } = await WebAssembly.instantiate(bytes, imports);
|
|
222
|
+
finalizeInit(instance, module);
|
|
223
|
+
|
|
224
|
+
// No proving key needed with Plonky3 STARKs!
|
|
225
|
+
log('[ZK Worker] ✅ Plonky3 WASM Loaded (no keys needed!)');
|
|
226
|
+
document.getElementById('status').innerText = 'Ready - Plonky3';
|
|
227
|
+
|
|
228
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'wasm_initialized' }));
|
|
229
|
+
|
|
230
|
+
} catch (err) {
|
|
231
|
+
log('[ZK Worker] FATAL: ' + err.message);
|
|
232
|
+
if (err.stack) log(err.stack);
|
|
233
|
+
document.getElementById('status').innerText = 'Error: ' + err.message;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function generateProof(payload) {
|
|
238
|
+
if (!wasm) throw new Error("WASM not initialized");
|
|
239
|
+
|
|
240
|
+
const { alloc, dealloc, generate_face_proof_from_ptrs } = wasm;
|
|
241
|
+
|
|
242
|
+
// 1. Prepare Data
|
|
243
|
+
const storedFloats = new Float64Array(payload.storedEmbedding);
|
|
244
|
+
const capturedFloats = new Float64Array(payload.capturedEmbedding);
|
|
245
|
+
|
|
246
|
+
const storedSize = storedFloats.length * 8;
|
|
247
|
+
const capturedSize = capturedFloats.length * 8;
|
|
248
|
+
|
|
249
|
+
// 2. Alloc
|
|
250
|
+
const storedPtr = alloc(storedSize);
|
|
251
|
+
const capturedPtr = alloc(capturedSize);
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
// 3. Write embeddings to WASM memory
|
|
255
|
+
// Use Uint8Array to copy bytes directly, avoiding "Byte offset is not aligned" errors
|
|
256
|
+
// if the allocator returns an address that isn't 8-byte aligned.
|
|
257
|
+
new Uint8Array(wasm.memory.buffer).set(new Uint8Array(storedFloats.buffer), storedPtr);
|
|
258
|
+
new Uint8Array(wasm.memory.buffer).set(new Uint8Array(capturedFloats.buffer), capturedPtr);
|
|
259
|
+
|
|
260
|
+
log('[ZK Worker] === Diagnostic Info ===');
|
|
261
|
+
|
|
262
|
+
// Prepare all parameters
|
|
263
|
+
const thresholdValue = payload.threshold || 0.6;
|
|
264
|
+
const nonceValue = BigInt(Date.now());
|
|
265
|
+
|
|
266
|
+
// Log parameter values
|
|
267
|
+
log(`Stored: ptr=${storedPtr}, count=${storedFloats.length}, first value=${storedFloats[0]}`);
|
|
268
|
+
log(`Captured: ptr=${capturedPtr}, count=${capturedFloats.length}, first value=${capturedFloats[0]}`);
|
|
269
|
+
log(`Threshold: ${thresholdValue}`);
|
|
270
|
+
log(`Nonce: ${nonceValue}`);
|
|
271
|
+
|
|
272
|
+
// Log parameter TYPES for debugging
|
|
273
|
+
log('[ZK Worker] === Parameter Types ===');
|
|
274
|
+
log(`storedPtr type: ${typeof storedPtr}, value: ${storedPtr}`);
|
|
275
|
+
log(`storedFloats.length type: ${typeof storedFloats.length}, value: ${storedFloats.length}`);
|
|
276
|
+
log(`capturedPtr type: ${typeof capturedPtr}, value: ${capturedPtr}`);
|
|
277
|
+
log(`capturedFloats.length type: ${typeof capturedFloats.length}, value: ${capturedFloats.length}`);
|
|
278
|
+
log(`threshold type: ${typeof thresholdValue}, value: ${thresholdValue}`);
|
|
279
|
+
log(`nonce type: ${typeof nonceValue}, value: ${nonceValue}`);
|
|
280
|
+
|
|
281
|
+
log('[ZK Worker] Calling Rust (Plonky3 - no PK needed)...');
|
|
282
|
+
|
|
283
|
+
const start = performance.now();
|
|
284
|
+
|
|
285
|
+
let ret;
|
|
286
|
+
try {
|
|
287
|
+
// 4. Call Rust (no PK parameters!)
|
|
288
|
+
// Plonky3 STARKs don't need proving keys
|
|
289
|
+
// Convert nonce to BigInt to match Rust u64 type
|
|
290
|
+
ret = generate_face_proof_from_ptrs(
|
|
291
|
+
storedPtr, storedFloats.length,
|
|
292
|
+
capturedPtr, capturedFloats.length,
|
|
293
|
+
thresholdValue,
|
|
294
|
+
nonceValue
|
|
295
|
+
);
|
|
296
|
+
log('[ZK Worker] Rust call returned successfully');
|
|
297
|
+
log(`[ZK Worker] Return value type: ${typeof ret}, isArray: ${Array.isArray(ret)}`);
|
|
298
|
+
if (Array.isArray(ret)) {
|
|
299
|
+
log(`[ZK Worker] Return array length: ${ret.length}`);
|
|
300
|
+
ret.forEach((val, idx) => {
|
|
301
|
+
log(`[ZK Worker] ret[${idx}] type: ${typeof val}, value: ${val}`);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
} catch (wasmErr) {
|
|
305
|
+
log('[ZK Worker] WASM threw during call: ' + wasmErr.message);
|
|
306
|
+
log('[ZK Worker] Error stack: ' + (wasmErr.stack || 'No stack available'));
|
|
307
|
+
throw wasmErr;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
var ptr = ret[0];
|
|
311
|
+
var len = ret[1];
|
|
312
|
+
var errPtr = ret[2];
|
|
313
|
+
var isErr = ret[3] !== 0;
|
|
314
|
+
|
|
315
|
+
if (isErr) {
|
|
316
|
+
// Extract error from externref table
|
|
317
|
+
const errorObj = takeFromExternrefTable0(errPtr);
|
|
318
|
+
throw new Error(errorObj);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// If success, read string from memory
|
|
322
|
+
const resultJson = getStringFromWasm0(ptr, len);
|
|
323
|
+
|
|
324
|
+
// Free the result string memory
|
|
325
|
+
if (wasm.__wbindgen_free) {
|
|
326
|
+
wasm.__wbindgen_free(ptr, len, 1);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const end = performance.now();
|
|
330
|
+
log(`[ZK Worker] ✅ Plonky3 proof generated in ${(end - start).toFixed(2)}ms`);
|
|
331
|
+
|
|
332
|
+
return resultJson;
|
|
333
|
+
|
|
334
|
+
} finally {
|
|
335
|
+
dealloc(storedPtr, storedSize);
|
|
336
|
+
dealloc(capturedPtr, capturedSize);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function handleMessage(event) {
|
|
341
|
+
try {
|
|
342
|
+
const msg = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
343
|
+
|
|
344
|
+
if (msg.type === 'init_wasm') {
|
|
345
|
+
initWasm(msg.payload.wasmBase64); // Access via payload
|
|
346
|
+
}
|
|
347
|
+
else if (msg.type === 'generate_proof') {
|
|
348
|
+
generateProof(msg.payload)
|
|
349
|
+
.then(result => {
|
|
350
|
+
log('[ZK Worker] Raw Result Type: ' + typeof result);
|
|
351
|
+
log('[ZK Worker] Raw Result Length: ' + result.length);
|
|
352
|
+
log('[ZK Worker] Raw Result Start: ' + result.substring(0, 50));
|
|
353
|
+
log('[ZK Worker] Raw Result End: ' + result.substring(result.length - 50));
|
|
354
|
+
|
|
355
|
+
let parsed;
|
|
356
|
+
try {
|
|
357
|
+
parsed = JSON.parse(result);
|
|
358
|
+
log('[ZK Worker] Parse Success. Keys: ' + Object.keys(parsed).join(', '));
|
|
359
|
+
if (parsed.proof) log('[ZK Worker] parsed.proof length: ' + parsed.proof.length);
|
|
360
|
+
} catch (e) {
|
|
361
|
+
log('[ZK Worker] JSON Parse Error: ' + e.message);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
365
|
+
type: 'proof_result',
|
|
366
|
+
data: parsed
|
|
367
|
+
}));
|
|
368
|
+
})
|
|
369
|
+
.catch(err => {
|
|
370
|
+
// Handle WASM panics properly
|
|
371
|
+
let errorMsg = err.toString();
|
|
372
|
+
if (err.message) errorMsg = err.message;
|
|
373
|
+
|
|
374
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
375
|
+
type: 'error',
|
|
376
|
+
error: errorMsg
|
|
377
|
+
}));
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
else if (msg.type === 'verify_proof') {
|
|
381
|
+
if (!wasm) throw new Error("WASM not initialized");
|
|
382
|
+
try {
|
|
383
|
+
const { verify_face_proof, __wbindgen_free } = wasm;
|
|
384
|
+
const payload = msg.payload;
|
|
385
|
+
|
|
386
|
+
// LOG THE RAW PAYLOAD GOING TO RUST
|
|
387
|
+
log('[ZK Worker] Verify Payload Keys: ' + Object.keys(payload).join(', '));
|
|
388
|
+
if(payload.public_inputs) {
|
|
389
|
+
log('[ZK Worker] Verify Public Inputs: ' + JSON.stringify(payload.public_inputs));
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const proofJson = JSON.stringify(payload);
|
|
393
|
+
|
|
394
|
+
log('[ZK Worker] Verifying proof... Input JSON len: ' + proofJson.length);
|
|
395
|
+
const sPtr = passStringToWasm0(proofJson, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
396
|
+
const sLen = WASM_VECTOR_LEN;
|
|
397
|
+
|
|
398
|
+
const ret = verify_face_proof(sPtr, sLen);
|
|
399
|
+
|
|
400
|
+
var ptr = ret[0];
|
|
401
|
+
var len = ret[1];
|
|
402
|
+
var errPtr = ret[2];
|
|
403
|
+
var isErr = ret[3] !== 0;
|
|
404
|
+
|
|
405
|
+
if (isErr) {
|
|
406
|
+
const errorObj = takeFromExternrefTable0(errPtr);
|
|
407
|
+
throw new Error(errorObj);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const resultJson = getStringFromWasm0(ptr, len);
|
|
411
|
+
log('[ZK Worker] Verify Result raw JSON: ' + resultJson);
|
|
412
|
+
|
|
413
|
+
if (__wbindgen_free) __wbindgen_free(ptr, len, 1);
|
|
414
|
+
|
|
415
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
416
|
+
type: 'verify_result',
|
|
417
|
+
data: JSON.parse(resultJson)
|
|
418
|
+
}));
|
|
419
|
+
} catch (e) {
|
|
420
|
+
log('[ZK Worker] Verify Error: ' + e.message);
|
|
421
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
422
|
+
type: 'error',
|
|
423
|
+
error: e.message
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
else if (msg.type === 'get_proof_hash') {
|
|
428
|
+
if (!wasm) throw new Error("WASM not initialized");
|
|
429
|
+
try {
|
|
430
|
+
const { get_proof_hash, __wbindgen_free } = wasm;
|
|
431
|
+
const proofJson = JSON.stringify(msg.payload);
|
|
432
|
+
|
|
433
|
+
const sPtr = passStringToWasm0(proofJson, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
434
|
+
const sLen = WASM_VECTOR_LEN;
|
|
435
|
+
|
|
436
|
+
const ret = get_proof_hash(sPtr, sLen);
|
|
437
|
+
|
|
438
|
+
var ptr = ret[0];
|
|
439
|
+
var len = ret[1];
|
|
440
|
+
|
|
441
|
+
const hashStr = getStringFromWasm0(ptr, len);
|
|
442
|
+
if (__wbindgen_free) __wbindgen_free(ptr, len, 1);
|
|
443
|
+
|
|
444
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
445
|
+
type: 'hash_result',
|
|
446
|
+
hash: hashStr
|
|
447
|
+
}));
|
|
448
|
+
} catch (e) {
|
|
449
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
450
|
+
type: 'error',
|
|
451
|
+
error: e.message
|
|
452
|
+
}));
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
} catch (e) {
|
|
456
|
+
log('Worker JSON Error: ' + e.message);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
window.addEventListener('message', handleMessage);
|
|
461
|
+
document.addEventListener('message', handleMessage);
|
|
462
|
+
|
|
463
|
+
if (window.ReactNativeWebView) {
|
|
464
|
+
setTimeout(() => {
|
|
465
|
+
window.ReactNativeWebView.postMessage(JSON.stringify({ type: 'ready' }));
|
|
466
|
+
}, 100);
|
|
467
|
+
}
|
|
468
|
+
</script>
|
|
469
|
+
</body>
|
|
470
|
+
|
|
471
|
+
</html>
|
|
472
|
+
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2026 JupiterMeta Labs
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
"use strict";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Copies onnxruntime-web assets from node_modules into assets/onnx/ so they
|
|
21
|
+
* can be bundled with the SDK and loaded offline (no CDN dependency at runtime).
|
|
22
|
+
*
|
|
23
|
+
* Runs automatically via the "postinstall" npm script.
|
|
24
|
+
* Safe to run multiple times (idempotent).
|
|
25
|
+
*
|
|
26
|
+
* Files copied:
|
|
27
|
+
* ort.min.js → assets/onnx/ort.min.js.txt (.txt so Metro treats it as a static asset)
|
|
28
|
+
* ort-wasm-simd.wasm → assets/onnx/ort-wasm-simd.wasm
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const fs = require("fs");
|
|
32
|
+
const path = require("path");
|
|
33
|
+
|
|
34
|
+
const DIST = path.resolve(__dirname, "../node_modules/onnxruntime-web/dist");
|
|
35
|
+
const DEST = path.resolve(__dirname, "../assets/onnx");
|
|
36
|
+
|
|
37
|
+
const COPIES = [
|
|
38
|
+
{ src: "ort.min.js", dst: "ort.min.js.txt" },
|
|
39
|
+
{ src: "ort-wasm-simd.wasm", dst: "ort-wasm-simd.wasm" },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
if (!fs.existsSync(DIST)) {
|
|
43
|
+
// onnxruntime-web not installed yet — happens when the SDK itself is installed
|
|
44
|
+
// as a package (consumers get pre-bundled files from assets/onnx/ in the npm tarball).
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fs.mkdirSync(DEST, { recursive: true });
|
|
49
|
+
|
|
50
|
+
for (const { src, dst } of COPIES) {
|
|
51
|
+
const srcPath = path.join(DIST, src);
|
|
52
|
+
const dstPath = path.join(DEST, dst);
|
|
53
|
+
|
|
54
|
+
if (!fs.existsSync(srcPath)) {
|
|
55
|
+
process.stderr.write(
|
|
56
|
+
`[copy-ort-assets] WARNING: ${src} not found in ${DIST}\n` +
|
|
57
|
+
` Is onnxruntime-web@1.16.x installed? Check devDependencies.\n`
|
|
58
|
+
);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fs.copyFileSync(srcPath, dstPath);
|
|
63
|
+
const size = Math.round(fs.statSync(dstPath).size / 1024);
|
|
64
|
+
process.stdout.write(`[copy-ort-assets] copied ${src} → assets/onnx/${dst} (${size} KB)\n`);
|
|
65
|
+
}
|