dop-wallet-v6 1.3.39 → 1.3.41

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.
@@ -0,0 +1,418 @@
1
+ "use strict";
2
+ /* eslint-disable no-bitwise */
3
+ /* eslint-disable no-plusplus */
4
+ /* eslint-disable camelcase */
5
+ /* eslint-disable import/no-extraneous-dependencies */
6
+ /* eslint-disable @typescript-eslint/strict-boolean-expressions */
7
+ /**
8
+ * RapidSnark Groth16 Integration for React Native
9
+ *
10
+ * This module provides a setRapidSnarkGroth16 function that mirrors the behavior
11
+ * of setSnarkJSGroth16 from dop-engine-v3, but uses rapidsnark for proof generation.
12
+ *
13
+ * Key differences from Node.js snarkjs:
14
+ * - Node.js: groth16.fullProve(inputs, wasmPath, zkeyPath) -> handles everything internally
15
+ * - Rapidsnark: groth16Prove(zkeyPath, witnessBase64) -> needs witness pre-calculated
16
+ *
17
+ * This module bridges the gap by:
18
+ * 1. Calculating witness from inputs using WASM
19
+ * 2. Saving zkey to device storage
20
+ * 3. Calling rapidsnark with zkeyPath and witnessBase64
21
+ */
22
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ var desc = Object.getOwnPropertyDescriptor(m, k);
25
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
26
+ desc = { enumerable: true, get: function() { return m[k]; } };
27
+ }
28
+ Object.defineProperty(o, k2, desc);
29
+ }) : (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ o[k2] = m[k];
32
+ }));
33
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
34
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
35
+ }) : function(o, v) {
36
+ o["default"] = v;
37
+ });
38
+ var __importStar = (this && this.__importStar) || function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.createExpoFSInterface = exports.createReactNativeFSInterface = exports.createCircomWitnessCalculator = exports.setRapidSnarkGroth16 = void 0;
47
+ const engine_1 = require("../core/engine");
48
+ /**
49
+ * Convert Uint8Array to base64 string
50
+ */
51
+ function uint8ArrayToBase64(data) {
52
+ // For React Native, we can use built-in btoa or a polyfill
53
+ if (typeof btoa !== 'undefined') {
54
+ let binary = '';
55
+ const bytes = new Uint8Array(data);
56
+ const len = bytes.byteLength;
57
+ for (let i = 0; i < len; i++) {
58
+ binary += String.fromCharCode(bytes[i]);
59
+ }
60
+ return btoa(binary);
61
+ }
62
+ // Fallback for environments without btoa
63
+ return Buffer.from(data).toString('base64');
64
+ }
65
+ /**
66
+ * Hash function for generating consistent zkey filenames
67
+ */
68
+ function hashBuffer(buffer) {
69
+ let hash = 0;
70
+ const len = buffer.length;
71
+ for (let i = 0; i < len; i++) {
72
+ hash = ((hash << 5) - hash) + buffer[i];
73
+ hash &= hash; // Convert to 32bit integer
74
+ }
75
+ return Math.abs(hash).toString(16).substring(0, 16);
76
+ }
77
+ /**
78
+ * Convert rapidsnark proof format to DOP Engine Proof format
79
+ *
80
+ * Rapidsnark returns:
81
+ * - proof.a: [x, y] as string[]
82
+ * - proof.b: [[x0, x1], [y0, y1]] as string[][]
83
+ * - proof.c: [x, y] as string[]
84
+ *
85
+ * DOP Engine expects:
86
+ * - pi_a: [string, string]
87
+ * - pi_b: [[string, string], [string, string]]
88
+ * - pi_c: [string, string]
89
+ */
90
+ function convertRapidsnarkProofToDOP(result) {
91
+ // Ensure proper tuple types
92
+ const pi_a = [result.proof.a[0], result.proof.a[1]];
93
+ const pi_b = [
94
+ [result.proof.b[0][0], result.proof.b[0][1]],
95
+ [result.proof.b[1][0], result.proof.b[1][1]],
96
+ ];
97
+ const pi_c = [result.proof.c[0], result.proof.c[1]];
98
+ return {
99
+ pi_a,
100
+ pi_b,
101
+ pi_c,
102
+ };
103
+ }
104
+ /**
105
+ * Set up RapidSnark as the groth16 implementation for DOP Engine
106
+ *
107
+ * This function should be called after initDOP() and before any proof generation.
108
+ * It configures the DOP Engine to use rapidsnark for ZK proof generation on React Native.
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * import { groth16Prove } from 'react-native-rapidsnark';
113
+ * import RNFS from 'react-native-fs';
114
+ * import { setRapidSnarkGroth16 } from 'new-dop-wallet-v3';
115
+ *
116
+ * // Create file system interface
117
+ * const fs: FileSystemInterface = {
118
+ * writeFile: async (path, data) => {
119
+ * if (data instanceof Uint8Array) {
120
+ * await RNFS.writeFile(path, uint8ArrayToBase64(data), 'base64');
121
+ * } else {
122
+ * await RNFS.writeFile(path, data, 'base64');
123
+ * }
124
+ * },
125
+ * readFile: async (path) => {
126
+ * const base64 = await RNFS.readFile(path, 'base64');
127
+ * return base64ToUint8Array(base64);
128
+ * },
129
+ * exists: RNFS.exists,
130
+ * unlink: RNFS.unlink,
131
+ * getCacheDirectory: () => RNFS.CachesDirectoryPath,
132
+ * };
133
+ *
134
+ * // Create witness calculator (using circom WASM)
135
+ * const witnessCalculator: WitnessCalculator = {
136
+ * calculateWTNSBin: async (wasmBuffer, inputs) => {
137
+ * // Use circom_runtime or similar
138
+ * const { WitnessCalculatorBuilder } = await import('circom_runtime');
139
+ * const wasmData = typeof wasmBuffer === 'string'
140
+ * ? base64ToUint8Array(wasmBuffer)
141
+ * : wasmBuffer;
142
+ * const wc = await WitnessCalculatorBuilder(wasmData);
143
+ * return await wc.calculateWTNSBin(inputs);
144
+ * },
145
+ * };
146
+ *
147
+ * // Initialize RapidSnark for DOP Engine
148
+ * await setRapidSnarkGroth16({
149
+ * groth16Prove,
150
+ * witnessCalculator,
151
+ * fs,
152
+ * });
153
+ * ```
154
+ */
155
+ async function setRapidSnarkGroth16(config) {
156
+ const { groth16Prove, witnessCalculator, fs, zkeyStorageDir, cacheZkeys = true, } = config;
157
+ const engine = (0, engine_1.getEngine)();
158
+ if (!engine) {
159
+ throw new Error('DOP Engine not initialized. Call initDOP() first.');
160
+ }
161
+ const baseDir = zkeyStorageDir || `${fs.getCacheDirectory()}/dop-zkeys`;
162
+ // Map to track saved zkey paths
163
+ const zkeyPathCache = new Map();
164
+ console.log('[RapidSnark] Setting up RapidSnark as groth16 implementation');
165
+ console.log('[RapidSnark] Zkey storage directory:', baseDir);
166
+ /**
167
+ * Save zkey to device and return the path
168
+ */
169
+ async function saveZkeyToDevice(zkeyBuffer, circuitId) {
170
+ const hash = hashBuffer(zkeyBuffer);
171
+ const cacheKey = `${circuitId}-${hash}`;
172
+ // Check if already cached
173
+ if (zkeyPathCache.has(cacheKey)) {
174
+ const cachedPath = zkeyPathCache.get(cacheKey);
175
+ if (cachedPath && await fs.exists(cachedPath)) {
176
+ console.log('[RapidSnark] Using cached zkey:', cachedPath);
177
+ return cachedPath;
178
+ }
179
+ }
180
+ // Generate unique filename
181
+ const filename = `circuit_${circuitId}_${hash}.zkey`;
182
+ const zkeyPath = `${baseDir}/${filename}`;
183
+ // Write zkey to device
184
+ console.log('[RapidSnark] Saving zkey to device:', zkeyPath);
185
+ await fs.writeFile(zkeyPath, zkeyBuffer);
186
+ // Cache the path
187
+ if (cacheZkeys) {
188
+ zkeyPathCache.set(cacheKey, zkeyPath);
189
+ }
190
+ return zkeyPath;
191
+ }
192
+ /**
193
+ * Cleanup temporary zkey file (if not caching)
194
+ */
195
+ async function cleanupZkey(zkeyPath) {
196
+ if (!cacheZkeys) {
197
+ try {
198
+ await fs.unlink(zkeyPath);
199
+ console.log('[RapidSnark] Cleaned up temporary zkey:', zkeyPath);
200
+ }
201
+ catch (error) {
202
+ console.warn('[RapidSnark] Failed to cleanup zkey:', error);
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Get circuit ID from inputs
208
+ */
209
+ function getCircuitIdFromInputs(formattedInputs) {
210
+ const nullifierCount = formattedInputs.nullifiers?.filter((n) => n !== undefined && n !== null && BigInt(n) !== BigInt(0)).length || 0;
211
+ const commitmentCount = formattedInputs.commitmentsOut?.filter((c) => c !== undefined && c !== null && BigInt(c) !== BigInt(0)).length || 0;
212
+ return `${nullifierCount}x${commitmentCount}`;
213
+ }
214
+ // Create groth16 implementation using rapidsnark
215
+ const rapidsnarkGroth16 = {
216
+ /**
217
+ * fullProveDop - matches the signature expected by DOP Engine
218
+ *
219
+ * This function:
220
+ * 1. Calculates witness from inputs using WASM
221
+ * 2. Saves zkey to device storage
222
+ * 3. Calls rapidsnark.groth16Prove
223
+ * 4. Returns proof in DOP Engine format
224
+ */
225
+ fullProveDop: async (formattedInputs, wasm, zkey, logger, _dat, progressCallback) => {
226
+ const circuitId = getCircuitIdFromInputs(formattedInputs);
227
+ let zkeyPath = null;
228
+ try {
229
+ logger.debug(`[RapidSnark] Starting proof generation for circuit ${circuitId}`);
230
+ progressCallback?.(5);
231
+ // Step 1: Calculate witness from inputs
232
+ logger.debug('[RapidSnark] Step 1: Calculating witness...');
233
+ progressCallback?.(10);
234
+ const wasmBuffer = typeof wasm === 'string'
235
+ ? new Uint8Array(Buffer.from(wasm, 'base64'))
236
+ : new Uint8Array(wasm);
237
+ const witnessBuffer = await witnessCalculator.calculateWTNSBin(wasmBuffer, formattedInputs);
238
+ logger.debug(`[RapidSnark] Witness calculated: ${witnessBuffer.byteLength} bytes`);
239
+ progressCallback?.(30);
240
+ // Step 2: Save zkey to device
241
+ logger.debug('[RapidSnark] Step 2: Preparing zkey...');
242
+ const zkeyBuffer = new Uint8Array(zkey);
243
+ zkeyPath = await saveZkeyToDevice(zkeyBuffer, circuitId);
244
+ logger.debug(`[RapidSnark] Zkey saved to: ${zkeyPath}`);
245
+ progressCallback?.(40);
246
+ // Step 3: Convert witness to base64
247
+ const witnessBase64 = uint8ArrayToBase64(witnessBuffer);
248
+ logger.debug(`[RapidSnark] Witness base64 length: ${witnessBase64.length}`);
249
+ progressCallback?.(50);
250
+ // Step 4: Generate proof with rapidsnark
251
+ logger.debug('[RapidSnark] Step 4: Generating proof with rapidsnark...');
252
+ const rapidsnarkResult = await groth16Prove(zkeyPath, witnessBase64);
253
+ logger.debug('[RapidSnark] Proof generated successfully');
254
+ progressCallback?.(90);
255
+ // Step 5: Convert to DOP Engine format
256
+ const proof = convertRapidsnarkProofToDOP(rapidsnarkResult);
257
+ const publicSignals = rapidsnarkResult.pub_signals;
258
+ progressCallback?.(100);
259
+ logger.debug('[RapidSnark] Proof generation complete');
260
+ return {
261
+ proof,
262
+ publicSignals,
263
+ };
264
+ }
265
+ catch (error) {
266
+ const errorMessage = error instanceof Error ? error.message : String(error);
267
+ logger.debug(`[RapidSnark] Error: ${errorMessage}`);
268
+ throw new Error(`RapidSnark proof generation failed: ${errorMessage}`);
269
+ }
270
+ finally {
271
+ // Cleanup if not caching
272
+ if (zkeyPath) {
273
+ await cleanupZkey(zkeyPath);
274
+ }
275
+ }
276
+ },
277
+ // fullProve - alias for compatibility
278
+ fullProve: async (inputs, wasmPath, zkeyPath, _logger) => {
279
+ // For fullProve, we need to read the files
280
+ const wasmBuffer = await fs.readFile(wasmPath);
281
+ const zkeyBuffer = await fs.readFile(zkeyPath);
282
+ return rapidsnarkGroth16.fullProveDop(inputs, wasmBuffer, zkeyBuffer, { debug: console.log }, null, undefined);
283
+ },
284
+ // verify - required by SnarkJSGroth16 interface
285
+ // Note: Rapidsnark verification is typically done on-chain or using snarkjs.verify
286
+ verify: async (_vkeyJson, _publicSignals, _proof) => {
287
+ console.warn('[RapidSnark] Proof verification should be done on-chain or using snarkjs.verify');
288
+ // For React Native, verification is typically not needed client-side
289
+ // The proof is verified on-chain when submitting the transaction
290
+ throw new Error('Proof verification is not supported in RapidSnark mode. Use on-chain verification.');
291
+ },
292
+ };
293
+ // Set the groth16 implementation on the engine
294
+ // Cast to SnarkJSGroth16 type (using unknown to bridge type differences)
295
+ engine.prover.setSnarkJSGroth16(rapidsnarkGroth16);
296
+ console.log('[RapidSnark] RapidSnark groth16 implementation set successfully');
297
+ }
298
+ exports.setRapidSnarkGroth16 = setRapidSnarkGroth16;
299
+ /**
300
+ * Helper: Create a WitnessCalculator using circom_runtime
301
+ *
302
+ * This is a factory function that creates a WitnessCalculator
303
+ * using the WitnessCalculatorBuilder from circom_runtime.
304
+ *
305
+ * @example
306
+ * ```typescript
307
+ * // In React Native, you'll need to handle WASM loading differently
308
+ * const witnessCalculator = await createCircomWitnessCalculator();
309
+ * ```
310
+ */
311
+ function createCircomWitnessCalculator() {
312
+ return {
313
+ calculateWTNSBin: async (wasmBuffer, inputs) => {
314
+ // Dynamic import circom_runtime
315
+ const { WitnessCalculatorBuilder } = await Promise.resolve().then(() => __importStar(require('circom_runtime')));
316
+ const wasmData = typeof wasmBuffer === 'string'
317
+ ? new Uint8Array(Buffer.from(wasmBuffer, 'base64'))
318
+ : wasmBuffer;
319
+ const witnessCalculator = await WitnessCalculatorBuilder(wasmData);
320
+ const witnessBin = await witnessCalculator.calculateWTNSBin(inputs);
321
+ return new Uint8Array(witnessBin);
322
+ },
323
+ };
324
+ }
325
+ exports.createCircomWitnessCalculator = createCircomWitnessCalculator;
326
+ /**
327
+ * Helper: Create a FileSystemInterface using react-native-fs
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * import RNFS from 'react-native-fs';
332
+ * const fs = createReactNativeFSInterface(RNFS);
333
+ * ```
334
+ */
335
+ function createReactNativeFSInterface(RNFS) {
336
+ return {
337
+ writeFile: async (path, data) => {
338
+ // Ensure directory exists
339
+ const dir = path.substring(0, path.lastIndexOf('/'));
340
+ try {
341
+ await RNFS.mkdir(dir);
342
+ }
343
+ catch {
344
+ // Directory might already exist
345
+ }
346
+ if (data instanceof Uint8Array) {
347
+ const base64 = uint8ArrayToBase64(data);
348
+ await RNFS.writeFile(path, base64, 'base64');
349
+ }
350
+ else {
351
+ await RNFS.writeFile(path, data, 'base64');
352
+ }
353
+ },
354
+ readFile: async (path) => {
355
+ const base64 = await RNFS.readFile(path, 'base64');
356
+ // Convert base64 to Uint8Array
357
+ if (typeof atob !== 'undefined') {
358
+ const binary = atob(base64);
359
+ const bytes = new Uint8Array(binary.length);
360
+ for (let i = 0; i < binary.length; i++) {
361
+ bytes[i] = binary.charCodeAt(i);
362
+ }
363
+ return bytes;
364
+ }
365
+ return new Uint8Array(Buffer.from(base64, 'base64'));
366
+ },
367
+ exists: RNFS.exists,
368
+ unlink: RNFS.unlink,
369
+ getCacheDirectory: () => RNFS.CachesDirectoryPath,
370
+ };
371
+ }
372
+ exports.createReactNativeFSInterface = createReactNativeFSInterface;
373
+ /**
374
+ * Helper: Create a FileSystemInterface using expo-file-system
375
+ *
376
+ * @example
377
+ * ```typescript
378
+ * import * as FileSystem from 'expo-file-system';
379
+ * const fs = createExpoFSInterface(FileSystem);
380
+ * ```
381
+ */
382
+ function createExpoFSInterface(ExpoFS) {
383
+ return {
384
+ writeFile: async (path, data) => {
385
+ // Ensure directory exists
386
+ const dir = path.substring(0, path.lastIndexOf('/'));
387
+ try {
388
+ await ExpoFS.makeDirectoryAsync(dir, { intermediates: true });
389
+ }
390
+ catch {
391
+ // Directory might already exist
392
+ }
393
+ const base64Data = data instanceof Uint8Array ? uint8ArrayToBase64(data) : data;
394
+ await ExpoFS.writeAsStringAsync(path, base64Data, { encoding: 'base64' });
395
+ },
396
+ readFile: async (path) => {
397
+ const base64 = await ExpoFS.readAsStringAsync(path, { encoding: 'base64' });
398
+ // Convert base64 to Uint8Array
399
+ if (typeof atob !== 'undefined') {
400
+ const binary = atob(base64);
401
+ const bytes = new Uint8Array(binary.length);
402
+ for (let i = 0; i < binary.length; i++) {
403
+ bytes[i] = binary.charCodeAt(i);
404
+ }
405
+ return bytes;
406
+ }
407
+ return new Uint8Array(Buffer.from(base64, 'base64'));
408
+ },
409
+ exists: async (path) => {
410
+ const info = await ExpoFS.getInfoAsync(path);
411
+ return info.exists;
412
+ },
413
+ unlink: ExpoFS.deleteAsync,
414
+ getCacheDirectory: () => ExpoFS.cacheDirectory || '/tmp',
415
+ };
416
+ }
417
+ exports.createExpoFSInterface = createExpoFSInterface;
418
+ //# sourceMappingURL=rapidsnark-groth16.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rapidsnark-groth16.js","sourceRoot":"","sources":["../../../../src/services/dop/crypto/rapidsnark-groth16.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-bitwise */\n/* eslint-disable no-plusplus */\n/* eslint-disable camelcase */\n/* eslint-disable import/no-extraneous-dependencies */\n/* eslint-disable @typescript-eslint/strict-boolean-expressions */\n/**\n * RapidSnark Groth16 Integration for React Native\n * \n * This module provides a setRapidSnarkGroth16 function that mirrors the behavior\n * of setSnarkJSGroth16 from dop-engine-v3, but uses rapidsnark for proof generation.\n * \n * Key differences from Node.js snarkjs:\n * - Node.js: groth16.fullProve(inputs, wasmPath, zkeyPath) -> handles everything internally\n * - Rapidsnark: groth16Prove(zkeyPath, witnessBase64) -> needs witness pre-calculated\n * \n * This module bridges the gap by:\n * 1. Calculating witness from inputs using WASM\n * 2. Saving zkey to device storage\n * 3. Calling rapidsnark with zkeyPath and witnessBase64\n */\n\nimport { FormattedCircuitInputsDop, Proof, SnarkJSGroth16 } from 'dop-engine-v3';\nimport { getEngine } from '../core/engine';\n\n// Type definitions matching react-native-rapidsnark\nexport interface RapidsnarkProofResult {\n proof: {\n a: string[];\n b: string[][];\n c: string[];\n };\n pub_signals: string[];\n}\n\n/**\n * Witness calculator interface\n * This should be provided by the mobile app using circom WASM\n */\nexport interface WitnessCalculator {\n /**\n * Calculate witness binary from circuit inputs\n * @param wasmBuffer - Circuit WASM file content (Uint8Array or base64 string)\n * @param inputs - Formatted circuit inputs\n * @returns Witness binary as Uint8Array\n */\n calculateWTNSBin(\n wasmBuffer: Uint8Array | string,\n inputs: FormattedCircuitInputsDop\n ): Promise<Uint8Array>;\n}\n\n/**\n * File system interface for React Native\n * Should be implemented using react-native-fs or expo-file-system\n */\nexport interface FileSystemInterface {\n /**\n * Write binary data to a file\n * @param path - Absolute file path\n * @param data - Binary data to write (Uint8Array or base64 string)\n */\n writeFile(path: string, data: Uint8Array | string): Promise<void>;\n \n /**\n * Read binary data from a file\n * @param path - Absolute file path\n * @returns Binary data as Uint8Array\n */\n readFile(path: string): Promise<Uint8Array>;\n \n /**\n * Check if a file exists\n * @param path - Absolute file path\n */\n exists(path: string): Promise<boolean>;\n \n /**\n * Delete a file\n * @param path - Absolute file path\n */\n unlink(path: string): Promise<void>;\n \n /**\n * Get the cache/temp directory path\n */\n getCacheDirectory(): string;\n}\n\n/**\n * Rapidsnark groth16 prove function type\n * Matches react-native-rapidsnark's groth16Prove signature\n */\nexport type Groth16ProveFunction = (\n zkeyPath: string,\n witnessBase64: string\n) => Promise<RapidsnarkProofResult>;\n\n/**\n * Configuration for setRapidSnarkGroth16\n */\nexport interface RapidSnarkGroth16Config {\n /**\n * Rapidsnark's groth16Prove function\n * Import from react-native-rapidsnark: import { groth16Prove } from 'react-native-rapidsnark'\n */\n groth16Prove: Groth16ProveFunction;\n \n /**\n * Witness calculator implementation\n * You can use circom_runtime or a custom implementation\n */\n witnessCalculator: WitnessCalculator;\n \n /**\n * File system interface for React Native\n * Use react-native-fs or expo-file-system\n */\n fs: FileSystemInterface;\n \n /**\n * Optional: Custom directory for storing zkey files\n * Defaults to fs.getCacheDirectory() + '/zkeys'\n */\n zkeyStorageDir?: string;\n \n /**\n * Optional: Whether to cache zkey files on device\n * Defaults to true for better performance\n */\n cacheZkeys?: boolean;\n}\n\n/**\n * Convert Uint8Array to base64 string\n */\nfunction uint8ArrayToBase64(data: Uint8Array): string {\n // For React Native, we can use built-in btoa or a polyfill\n if (typeof btoa !== 'undefined') {\n let binary = '';\n const bytes = new Uint8Array(data);\n const len = bytes.byteLength;\n for (let i = 0; i < len; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n \n // Fallback for environments without btoa\n return Buffer.from(data).toString('base64');\n}\n\n/**\n * Hash function for generating consistent zkey filenames\n */\nfunction hashBuffer(buffer: ArrayLike<number>): string {\n let hash = 0;\n const len = buffer.length;\n for (let i = 0; i < len; i++) {\n hash = ((hash << 5) - hash) + buffer[i];\n hash &= hash; // Convert to 32bit integer\n }\n return Math.abs(hash).toString(16).substring(0, 16);\n}\n\n/**\n * Convert rapidsnark proof format to DOP Engine Proof format\n * \n * Rapidsnark returns:\n * - proof.a: [x, y] as string[]\n * - proof.b: [[x0, x1], [y0, y1]] as string[][]\n * - proof.c: [x, y] as string[]\n * \n * DOP Engine expects:\n * - pi_a: [string, string]\n * - pi_b: [[string, string], [string, string]]\n * - pi_c: [string, string]\n */\nfunction convertRapidsnarkProofToDOP(result: RapidsnarkProofResult): Proof {\n // Ensure proper tuple types\n const pi_a: [string, string] = [result.proof.a[0], result.proof.a[1]];\n const pi_b: [[string, string], [string, string]] = [\n [result.proof.b[0][0], result.proof.b[0][1]],\n [result.proof.b[1][0], result.proof.b[1][1]],\n ];\n const pi_c: [string, string] = [result.proof.c[0], result.proof.c[1]];\n \n return {\n pi_a,\n pi_b,\n pi_c,\n };\n}\n\n/**\n * Set up RapidSnark as the groth16 implementation for DOP Engine\n * \n * This function should be called after initDOP() and before any proof generation.\n * It configures the DOP Engine to use rapidsnark for ZK proof generation on React Native.\n * \n * @example\n * ```typescript\n * import { groth16Prove } from 'react-native-rapidsnark';\n * import RNFS from 'react-native-fs';\n * import { setRapidSnarkGroth16 } from 'new-dop-wallet-v3';\n * \n * // Create file system interface\n * const fs: FileSystemInterface = {\n * writeFile: async (path, data) => {\n * if (data instanceof Uint8Array) {\n * await RNFS.writeFile(path, uint8ArrayToBase64(data), 'base64');\n * } else {\n * await RNFS.writeFile(path, data, 'base64');\n * }\n * },\n * readFile: async (path) => {\n * const base64 = await RNFS.readFile(path, 'base64');\n * return base64ToUint8Array(base64);\n * },\n * exists: RNFS.exists,\n * unlink: RNFS.unlink,\n * getCacheDirectory: () => RNFS.CachesDirectoryPath,\n * };\n * \n * // Create witness calculator (using circom WASM)\n * const witnessCalculator: WitnessCalculator = {\n * calculateWTNSBin: async (wasmBuffer, inputs) => {\n * // Use circom_runtime or similar\n * const { WitnessCalculatorBuilder } = await import('circom_runtime');\n * const wasmData = typeof wasmBuffer === 'string' \n * ? base64ToUint8Array(wasmBuffer) \n * : wasmBuffer;\n * const wc = await WitnessCalculatorBuilder(wasmData);\n * return await wc.calculateWTNSBin(inputs);\n * },\n * };\n * \n * // Initialize RapidSnark for DOP Engine\n * await setRapidSnarkGroth16({\n * groth16Prove,\n * witnessCalculator,\n * fs,\n * });\n * ```\n */\nexport async function setRapidSnarkGroth16(config: RapidSnarkGroth16Config): Promise<void> {\n const {\n groth16Prove,\n witnessCalculator,\n fs,\n zkeyStorageDir,\n cacheZkeys = true,\n } = config;\n \n const engine = getEngine();\n \n if (!engine) {\n throw new Error('DOP Engine not initialized. Call initDOP() first.');\n }\n \n const baseDir = zkeyStorageDir || `${fs.getCacheDirectory()}/dop-zkeys`;\n \n // Map to track saved zkey paths\n const zkeyPathCache = new Map<string, string>();\n \n console.log('[RapidSnark] Setting up RapidSnark as groth16 implementation');\n console.log('[RapidSnark] Zkey storage directory:', baseDir);\n \n /**\n * Save zkey to device and return the path\n */\n async function saveZkeyToDevice(zkeyBuffer: Uint8Array, circuitId: string): Promise<string> {\n const hash = hashBuffer(zkeyBuffer);\n const cacheKey = `${circuitId}-${hash}`;\n \n // Check if already cached\n if (zkeyPathCache.has(cacheKey)) {\n const cachedPath = zkeyPathCache.get(cacheKey);\n if (cachedPath && await fs.exists(cachedPath)) {\n console.log('[RapidSnark] Using cached zkey:', cachedPath);\n return cachedPath;\n }\n }\n \n // Generate unique filename\n const filename = `circuit_${circuitId}_${hash}.zkey`;\n const zkeyPath = `${baseDir}/${filename}`;\n \n // Write zkey to device\n console.log('[RapidSnark] Saving zkey to device:', zkeyPath);\n await fs.writeFile(zkeyPath, zkeyBuffer);\n \n // Cache the path\n if (cacheZkeys) {\n zkeyPathCache.set(cacheKey, zkeyPath);\n }\n \n return zkeyPath;\n }\n \n /**\n * Cleanup temporary zkey file (if not caching)\n */\n async function cleanupZkey(zkeyPath: string): Promise<void> {\n if (!cacheZkeys) {\n try {\n await fs.unlink(zkeyPath);\n console.log('[RapidSnark] Cleaned up temporary zkey:', zkeyPath);\n } catch (error) {\n console.warn('[RapidSnark] Failed to cleanup zkey:', error);\n }\n }\n }\n \n /**\n * Get circuit ID from inputs\n */\n function getCircuitIdFromInputs(formattedInputs: FormattedCircuitInputsDop): string {\n const nullifierCount = formattedInputs.nullifiers?.filter(\n (n: bigint | string) => n !== undefined && n !== null && BigInt(n) !== BigInt(0)\n ).length || 0;\n \n const commitmentCount = formattedInputs.commitmentsOut?.filter(\n (c: bigint | string) => c !== undefined && c !== null && BigInt(c) !== BigInt(0)\n ).length || 0;\n \n return `${nullifierCount}x${commitmentCount}`;\n }\n \n // Create groth16 implementation using rapidsnark\n const rapidsnarkGroth16 = {\n /**\n * fullProveDop - matches the signature expected by DOP Engine\n * \n * This function:\n * 1. Calculates witness from inputs using WASM\n * 2. Saves zkey to device storage\n * 3. Calls rapidsnark.groth16Prove\n * 4. Returns proof in DOP Engine format\n */\n fullProveDop: async (\n formattedInputs: FormattedCircuitInputsDop,\n wasm: Uint8Array | string,\n zkey: ArrayLike<number>,\n logger: { debug: (log: string) => void },\n _dat: unknown,\n progressCallback?: (progress: number) => void\n ): Promise<{ proof: Proof; publicSignals: string[] }> => {\n const circuitId = getCircuitIdFromInputs(formattedInputs);\n let zkeyPath: string | null = null;\n \n try {\n logger.debug(`[RapidSnark] Starting proof generation for circuit ${circuitId}`);\n progressCallback?.(5);\n \n // Step 1: Calculate witness from inputs\n logger.debug('[RapidSnark] Step 1: Calculating witness...');\n progressCallback?.(10);\n \n const wasmBuffer = typeof wasm === 'string' \n ? new Uint8Array(Buffer.from(wasm, 'base64'))\n : new Uint8Array(wasm);\n \n const witnessBuffer = await witnessCalculator.calculateWTNSBin(wasmBuffer, formattedInputs);\n logger.debug(`[RapidSnark] Witness calculated: ${witnessBuffer.byteLength} bytes`);\n progressCallback?.(30);\n \n // Step 2: Save zkey to device\n logger.debug('[RapidSnark] Step 2: Preparing zkey...');\n const zkeyBuffer = new Uint8Array(zkey);\n zkeyPath = await saveZkeyToDevice(zkeyBuffer, circuitId);\n logger.debug(`[RapidSnark] Zkey saved to: ${zkeyPath}`);\n progressCallback?.(40);\n \n // Step 3: Convert witness to base64\n const witnessBase64 = uint8ArrayToBase64(witnessBuffer);\n logger.debug(`[RapidSnark] Witness base64 length: ${witnessBase64.length}`);\n progressCallback?.(50);\n \n // Step 4: Generate proof with rapidsnark\n logger.debug('[RapidSnark] Step 4: Generating proof with rapidsnark...');\n const rapidsnarkResult = await groth16Prove(zkeyPath, witnessBase64);\n logger.debug('[RapidSnark] Proof generated successfully');\n progressCallback?.(90);\n \n // Step 5: Convert to DOP Engine format\n const proof = convertRapidsnarkProofToDOP(rapidsnarkResult);\n const publicSignals = rapidsnarkResult.pub_signals;\n progressCallback?.(100);\n \n logger.debug('[RapidSnark] Proof generation complete');\n \n return {\n proof,\n publicSignals,\n };\n \n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.debug(`[RapidSnark] Error: ${errorMessage}`);\n throw new Error(`RapidSnark proof generation failed: ${errorMessage}`);\n \n } finally {\n // Cleanup if not caching\n if (zkeyPath) {\n await cleanupZkey(zkeyPath);\n }\n }\n },\n \n // fullProve - alias for compatibility\n fullProve: async (\n inputs: FormattedCircuitInputsDop,\n wasmPath: string,\n zkeyPath: string,\n _logger?: unknown\n ): Promise<{ proof: Proof; publicSignals: string[] }> => {\n // For fullProve, we need to read the files\n const wasmBuffer = await fs.readFile(wasmPath);\n const zkeyBuffer = await fs.readFile(zkeyPath);\n \n return rapidsnarkGroth16.fullProveDop(\n inputs,\n wasmBuffer,\n zkeyBuffer,\n { debug: console.log },\n null,\n undefined\n );\n },\n \n // verify - required by SnarkJSGroth16 interface\n // Note: Rapidsnark verification is typically done on-chain or using snarkjs.verify\n verify: async (\n _vkeyJson: object,\n _publicSignals: string[],\n _proof: Proof\n ): Promise<boolean> => {\n console.warn('[RapidSnark] Proof verification should be done on-chain or using snarkjs.verify');\n // For React Native, verification is typically not needed client-side\n // The proof is verified on-chain when submitting the transaction\n throw new Error('Proof verification is not supported in RapidSnark mode. Use on-chain verification.');\n },\n };\n \n // Set the groth16 implementation on the engine\n // Cast to SnarkJSGroth16 type (using unknown to bridge type differences)\n engine.prover.setSnarkJSGroth16(rapidsnarkGroth16 as unknown as SnarkJSGroth16);\n \n console.log('[RapidSnark] RapidSnark groth16 implementation set successfully');\n}\n\n/**\n * Helper: Create a WitnessCalculator using circom_runtime\n * \n * This is a factory function that creates a WitnessCalculator\n * using the WitnessCalculatorBuilder from circom_runtime.\n * \n * @example\n * ```typescript\n * // In React Native, you'll need to handle WASM loading differently\n * const witnessCalculator = await createCircomWitnessCalculator();\n * ```\n */\nexport function createCircomWitnessCalculator(): WitnessCalculator {\n return {\n calculateWTNSBin: async (wasmBuffer: Uint8Array | string, inputs: FormattedCircuitInputsDop) => {\n // Dynamic import circom_runtime\n const { WitnessCalculatorBuilder } = await import('circom_runtime');\n \n const wasmData = typeof wasmBuffer === 'string'\n ? new Uint8Array(Buffer.from(wasmBuffer, 'base64'))\n : wasmBuffer;\n \n const witnessCalculator = await WitnessCalculatorBuilder(wasmData);\n const witnessBin = await witnessCalculator.calculateWTNSBin(inputs);\n \n return new Uint8Array(witnessBin);\n },\n };\n}\n\n/**\n * Helper: Create a FileSystemInterface using react-native-fs\n * \n * @example\n * ```typescript\n * import RNFS from 'react-native-fs';\n * const fs = createReactNativeFSInterface(RNFS);\n * ```\n */\nexport function createReactNativeFSInterface(RNFS: {\n writeFile: (path: string, content: string, encoding: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n exists: (path: string) => Promise<boolean>;\n unlink: (path: string) => Promise<void>;\n CachesDirectoryPath: string;\n mkdir: (path: string) => Promise<void>;\n}): FileSystemInterface {\n return {\n writeFile: async (path: string, data: Uint8Array | string) => {\n // Ensure directory exists\n const dir = path.substring(0, path.lastIndexOf('/'));\n try {\n await RNFS.mkdir(dir);\n } catch {\n // Directory might already exist\n }\n \n if (data instanceof Uint8Array) {\n const base64 = uint8ArrayToBase64(data);\n await RNFS.writeFile(path, base64, 'base64');\n } else {\n await RNFS.writeFile(path, data, 'base64');\n }\n },\n \n readFile: async (path: string) => {\n const base64 = await RNFS.readFile(path, 'base64');\n \n // Convert base64 to Uint8Array\n if (typeof atob !== 'undefined') {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n \n return new Uint8Array(Buffer.from(base64, 'base64'));\n },\n \n exists: RNFS.exists,\n \n unlink: RNFS.unlink,\n \n getCacheDirectory: () => RNFS.CachesDirectoryPath,\n };\n}\n\n/**\n * Helper: Create a FileSystemInterface using expo-file-system\n * \n * @example\n * ```typescript\n * import * as FileSystem from 'expo-file-system';\n * const fs = createExpoFSInterface(FileSystem);\n * ```\n */\nexport function createExpoFSInterface(ExpoFS: {\n writeAsStringAsync: (path: string, content: string, options?: { encoding: string }) => Promise<void>;\n readAsStringAsync: (path: string, options?: { encoding: string }) => Promise<string>;\n getInfoAsync: (path: string) => Promise<{ exists: boolean }>;\n deleteAsync: (path: string) => Promise<void>;\n cacheDirectory: string | null;\n makeDirectoryAsync: (path: string, options?: { intermediates: boolean }) => Promise<void>;\n}): FileSystemInterface {\n return {\n writeFile: async (path: string, data: Uint8Array | string) => {\n // Ensure directory exists\n const dir = path.substring(0, path.lastIndexOf('/'));\n try {\n await ExpoFS.makeDirectoryAsync(dir, { intermediates: true });\n } catch {\n // Directory might already exist\n }\n \n const base64Data = data instanceof Uint8Array ? uint8ArrayToBase64(data) : data;\n await ExpoFS.writeAsStringAsync(path, base64Data, { encoding: 'base64' });\n },\n \n readFile: async (path: string) => {\n const base64 = await ExpoFS.readAsStringAsync(path, { encoding: 'base64' });\n \n // Convert base64 to Uint8Array\n if (typeof atob !== 'undefined') {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n }\n \n return new Uint8Array(Buffer.from(base64, 'base64'));\n },\n \n exists: async (path: string) => {\n const info = await ExpoFS.getInfoAsync(path);\n return info.exists;\n },\n \n unlink: ExpoFS.deleteAsync,\n \n getCacheDirectory: () => ExpoFS.cacheDirectory || '/tmp',\n };\n}\n"]}