dop-wallet-v6 1.3.33 → 1.3.34
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/dist/services/dop/core/react-native-prover-setup.d.ts +33 -13
- package/dist/services/dop/core/react-native-prover-setup.js +183 -67
- package/dist/services/dop/core/react-native-prover-setup.js.map +1 -1
- package/dist/services/dop/crypto/mopro-circuit-loader.d.ts +103 -0
- package/dist/services/dop/crypto/mopro-circuit-loader.js +308 -0
- package/dist/services/dop/crypto/mopro-circuit-loader.js.map +1 -0
- package/dist/services/dop/crypto/mopro-prover-adapter.d.ts +117 -0
- package/dist/services/dop/crypto/mopro-prover-adapter.js +243 -0
- package/dist/services/dop/crypto/mopro-prover-adapter.js.map +1 -0
- package/package.json +1 -1
- package/react-native.js +7 -0
|
@@ -1,31 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* React Native Prover Setup
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* This module enables fully on-device zero-knowledge proof generation in React Native
|
|
5
|
+
* using Mopro (Mobile Prover) toolkit.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* SUPPORTED APPROACHES:
|
|
8
|
+
* 1. Mopro (Recommended) - Full on-device proof generation with native performance
|
|
9
|
+
* 2. Backend Witness Service - Generate witness on backend, proof on device with Rapidsnark
|
|
10
|
+
* 3. Encrypted Transfers Only - Shield operations without proof generation
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* MOPRO INTEGRATION:
|
|
13
|
+
* - Witness generation: Native C++/Rust (2-29x faster than browser)
|
|
14
|
+
* - Proof generation: Native Arkworks or Rapidsnark (8-15x faster than browser)
|
|
15
|
+
* - No WebAssembly required (bypasses React Native limitations)
|
|
16
|
+
* - No backend service needed
|
|
11
17
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* 2. Use encrypted transfers only (which don't require proofs)
|
|
15
|
-
* 3. Wait for DOP to release React Native-compatible proof generation
|
|
18
|
+
* @see https://zkmopro.org/docs/intro
|
|
19
|
+
* @see MOPRO_INTEGRATION_PLAN.md
|
|
16
20
|
*/
|
|
21
|
+
import { type MoproCircuitLoader } from '../crypto/mopro-circuit-loader';
|
|
17
22
|
/**
|
|
18
23
|
* Check if proof generation is available in React Native
|
|
19
|
-
*
|
|
24
|
+
* Tries Mopro first (recommended), then falls back to Rapidsnark backend approach
|
|
20
25
|
*/
|
|
21
|
-
export declare const checkReactNativeProverSupport: () => Promise<
|
|
26
|
+
export declare const checkReactNativeProverSupport: () => Promise<{
|
|
27
|
+
available: boolean;
|
|
28
|
+
method: 'mopro' | 'rapidsnark-backend' | 'none';
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Setup Mopro prover for React Native
|
|
33
|
+
* Configures DOP Engine to use Mopro for fully on-device proof generation
|
|
34
|
+
*
|
|
35
|
+
* @param useRapidsnark - Use Rapidsnark backend instead of Arkworks (default: false)
|
|
36
|
+
* @returns true if setup successful
|
|
37
|
+
*/
|
|
38
|
+
export declare const setupMoproProver: (useRapidsnark?: boolean) => Promise<boolean>;
|
|
22
39
|
/**
|
|
23
40
|
* Setup Groth16 prover for React Native
|
|
24
|
-
*
|
|
41
|
+
* Tries Mopro first, falls back to checking Rapidsnark backend availability
|
|
25
42
|
*/
|
|
26
43
|
export declare const setupReactNativeProver: () => Promise<boolean>;
|
|
27
44
|
/**
|
|
28
45
|
* Auto-setup prover if in React Native environment
|
|
29
|
-
* Currently just checks and warns about lack of support
|
|
30
46
|
*/
|
|
31
47
|
export declare const autoSetupProverForReactNative: () => Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Get circuit loader instance (for manual circuit preloading)
|
|
50
|
+
*/
|
|
51
|
+
export declare const getCircuitLoader: () => Promise<MoproCircuitLoader | null>;
|
|
@@ -2,105 +2,205 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* React Native Prover Setup
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* This module enables fully on-device zero-knowledge proof generation in React Native
|
|
6
|
+
* using Mopro (Mobile Prover) toolkit.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* SUPPORTED APPROACHES:
|
|
9
|
+
* 1. Mopro (Recommended) - Full on-device proof generation with native performance
|
|
10
|
+
* 2. Backend Witness Service - Generate witness on backend, proof on device with Rapidsnark
|
|
11
|
+
* 3. Encrypted Transfers Only - Shield operations without proof generation
|
|
9
12
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
13
|
+
* MOPRO INTEGRATION:
|
|
14
|
+
* - Witness generation: Native C++/Rust (2-29x faster than browser)
|
|
15
|
+
* - Proof generation: Native Arkworks or Rapidsnark (8-15x faster than browser)
|
|
16
|
+
* - No WebAssembly required (bypasses React Native limitations)
|
|
17
|
+
* - No backend service needed
|
|
12
18
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* 2. Use encrypted transfers only (which don't require proofs)
|
|
16
|
-
* 3. Wait for DOP to release React Native-compatible proof generation
|
|
19
|
+
* @see https://zkmopro.org/docs/intro
|
|
20
|
+
* @see MOPRO_INTEGRATION_PLAN.md
|
|
17
21
|
*/
|
|
18
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.autoSetupProverForReactNative = exports.setupReactNativeProver = exports.checkReactNativeProverSupport = void 0;
|
|
23
|
+
exports.getCircuitLoader = exports.autoSetupProverForReactNative = exports.setupReactNativeProver = exports.setupMoproProver = exports.checkReactNativeProverSupport = void 0;
|
|
24
|
+
const prover_1 = require("./prover");
|
|
20
25
|
const runtime_1 = require("../util/runtime");
|
|
21
26
|
const react_native_rapidsnark_prover_1 = require("../crypto/react-native-rapidsnark-prover");
|
|
27
|
+
const mopro_prover_adapter_1 = require("../crypto/mopro-prover-adapter");
|
|
28
|
+
const mopro_circuit_loader_1 = require("../crypto/mopro-circuit-loader");
|
|
22
29
|
/**
|
|
23
30
|
* Check if proof generation is available in React Native
|
|
24
|
-
*
|
|
31
|
+
* Tries Mopro first (recommended), then falls back to Rapidsnark backend approach
|
|
25
32
|
*/
|
|
26
33
|
const checkReactNativeProverSupport = async () => {
|
|
27
34
|
if (!runtime_1.isReactNative) {
|
|
28
|
-
return
|
|
35
|
+
return {
|
|
36
|
+
available: true,
|
|
37
|
+
method: 'none',
|
|
38
|
+
message: 'Not in React Native environment'
|
|
39
|
+
};
|
|
29
40
|
}
|
|
30
41
|
try {
|
|
31
|
-
//
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
console.
|
|
36
|
-
console.
|
|
37
|
-
console.
|
|
38
|
-
console.
|
|
39
|
-
console.
|
|
40
|
-
console.
|
|
41
|
-
console.
|
|
42
|
-
console.
|
|
43
|
-
console.
|
|
44
|
-
console.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
console.error(' without generating proofs for private transfers.');
|
|
51
|
-
console.error('');
|
|
52
|
-
console.error('3. Wait for Native Support:');
|
|
53
|
-
console.error(' DOP is working on React Native-compatible proof');
|
|
54
|
-
console.error(' generation using @iden3/react-native-rapidsnark.');
|
|
55
|
-
console.error('');
|
|
56
|
-
console.error('Operations that require proofs:');
|
|
57
|
-
console.error(' - Private transfers (sendERC20Token)');
|
|
58
|
-
console.error(' - Private NFT transfers');
|
|
59
|
-
console.error(' - Unshield operations (decryptERC20Token)');
|
|
60
|
-
console.error('');
|
|
61
|
-
console.error('Operations that work without proofs:');
|
|
62
|
-
console.error(' - Shield operations (encryptERC20Token)');
|
|
63
|
-
console.error(' - Balance queries');
|
|
64
|
-
console.error(' - Wallet creation');
|
|
65
|
-
console.error(' - Transaction history');
|
|
66
|
-
console.error('');
|
|
67
|
-
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
68
|
-
return false;
|
|
42
|
+
// Try to initialize Mopro (fully on-device)
|
|
43
|
+
const moproInit = await (0, mopro_prover_adapter_1.initializeMopro)();
|
|
44
|
+
const rnfsInit = await (0, mopro_circuit_loader_1.initializeRNFS)();
|
|
45
|
+
if (moproInit && rnfsInit && (0, mopro_prover_adapter_1.isMoproAvailable)() && (0, mopro_circuit_loader_1.isRNFSAvailable)()) {
|
|
46
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
47
|
+
console.log('✅ MOPRO PROOF GENERATION AVAILABLE');
|
|
48
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
49
|
+
console.log('');
|
|
50
|
+
console.log('🚀 Fully on-device proof generation enabled via Mopro');
|
|
51
|
+
console.log(' - No backend witness service needed');
|
|
52
|
+
console.log(' - Native performance (8-25x faster than browser)');
|
|
53
|
+
console.log(' - All DOP operations work fully on-device');
|
|
54
|
+
console.log('');
|
|
55
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
56
|
+
return {
|
|
57
|
+
available: true,
|
|
58
|
+
method: 'mopro',
|
|
59
|
+
message: 'Mopro initialized successfully'
|
|
60
|
+
};
|
|
69
61
|
}
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
// Mopro not available, try Rapidsnark backend approach
|
|
63
|
+
const rapidsnarkInit = await (0, react_native_rapidsnark_prover_1.initializeRapidsnark)();
|
|
64
|
+
if (rapidsnarkInit && (0, react_native_rapidsnark_prover_1.isRapidsnarkAvailable)()) {
|
|
65
|
+
console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
66
|
+
console.warn('⚠️ RAPIDSNARK AVAILABLE (BACKEND WITNESS REQUIRED)');
|
|
67
|
+
console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
68
|
+
console.warn('');
|
|
69
|
+
console.warn('Rapidsnark is available for proof generation, but witness');
|
|
70
|
+
console.warn('calculation must be done on a backend service.');
|
|
71
|
+
console.warn('');
|
|
72
|
+
console.warn('For fully on-device proof generation, install Mopro:');
|
|
73
|
+
console.warn(' npm install mopro-ffi react-native-fs');
|
|
74
|
+
console.warn(' See: https://zkmopro.org/docs/setup/react-native-setup');
|
|
75
|
+
console.warn('');
|
|
76
|
+
console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
77
|
+
return {
|
|
78
|
+
available: true,
|
|
79
|
+
method: 'rapidsnark-backend',
|
|
80
|
+
message: 'Rapidsnark available, backend witness required'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Neither Mopro nor Rapidsnark available
|
|
84
|
+
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
85
|
+
console.error('⚠️ REACT NATIVE PROOF GENERATION NOT AVAILABLE');
|
|
86
|
+
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
87
|
+
console.error('');
|
|
88
|
+
console.error('The DOP SDK cannot generate zero-knowledge proofs in');
|
|
89
|
+
console.error('React Native because SnarkJS requires WebAssembly.');
|
|
90
|
+
console.error('');
|
|
91
|
+
console.error('RECOMMENDED SOLUTION:');
|
|
92
|
+
console.error('');
|
|
93
|
+
console.error('Install Mopro for fully on-device proof generation:');
|
|
94
|
+
console.error(' npm install mopro-ffi react-native-fs');
|
|
95
|
+
console.error(' Setup guide: https://zkmopro.org/docs/setup/react-native-setup');
|
|
96
|
+
console.error('');
|
|
97
|
+
console.error('Benefits:');
|
|
98
|
+
console.error(' ✅ No backend service needed');
|
|
99
|
+
console.error(' ✅ 8-25x faster than browser');
|
|
100
|
+
console.error(' ✅ Native iOS/Android performance');
|
|
101
|
+
console.error(' ✅ Privacy-preserving (no data leaves device)');
|
|
102
|
+
console.error('');
|
|
103
|
+
console.error('ALTERNATIVE SOLUTIONS:');
|
|
104
|
+
console.error('');
|
|
105
|
+
console.error('1. Backend Witness Service:');
|
|
106
|
+
console.error(' Install @iden3/react-native-rapidsnark for proof generation');
|
|
107
|
+
console.error(' Set up backend service for witness calculation');
|
|
108
|
+
console.error('');
|
|
109
|
+
console.error('2. Encrypted Transfers Only:');
|
|
110
|
+
console.error(' Shield operations work without proof generation');
|
|
111
|
+
console.error('');
|
|
112
|
+
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
113
|
+
return {
|
|
114
|
+
available: false,
|
|
115
|
+
method: 'none',
|
|
116
|
+
message: 'No proof generation method available'
|
|
117
|
+
};
|
|
83
118
|
}
|
|
84
119
|
catch (error) {
|
|
85
120
|
console.error('Error checking React Native prover support:', error);
|
|
86
|
-
return
|
|
121
|
+
return {
|
|
122
|
+
available: false,
|
|
123
|
+
method: 'none',
|
|
124
|
+
message: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
125
|
+
};
|
|
87
126
|
}
|
|
88
127
|
};
|
|
89
128
|
exports.checkReactNativeProverSupport = checkReactNativeProverSupport;
|
|
129
|
+
/**
|
|
130
|
+
* Setup Mopro prover for React Native
|
|
131
|
+
* Configures DOP Engine to use Mopro for fully on-device proof generation
|
|
132
|
+
*
|
|
133
|
+
* @param useRapidsnark - Use Rapidsnark backend instead of Arkworks (default: false)
|
|
134
|
+
* @returns true if setup successful
|
|
135
|
+
*/
|
|
136
|
+
const setupMoproProver = async (useRapidsnark = false) => {
|
|
137
|
+
if (!runtime_1.isReactNative) {
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
// Initialize Mopro and RNFS
|
|
142
|
+
const moproInit = await (0, mopro_prover_adapter_1.initializeMopro)();
|
|
143
|
+
const rnfsInit = await (0, mopro_circuit_loader_1.initializeRNFS)();
|
|
144
|
+
if (!moproInit || !rnfsInit) {
|
|
145
|
+
console.error('❌ Failed to initialize Mopro or RNFS');
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
console.log('🔧 Setting up Mopro prover for DOP Engine...');
|
|
149
|
+
// Create Mopro adapter
|
|
150
|
+
const proofLib = useRapidsnark ? mopro_prover_adapter_1.ProofLib.Rapidsnark : mopro_prover_adapter_1.ProofLib.Arkworks;
|
|
151
|
+
const moproAdapter = new mopro_prover_adapter_1.MoproProverAdapter(proofLib);
|
|
152
|
+
// Create circuit loader
|
|
153
|
+
const circuitLoader = await (0, mopro_circuit_loader_1.createCircuitLoader)();
|
|
154
|
+
// Get DOP Engine prover instance
|
|
155
|
+
const prover = (0, prover_1.getProver)();
|
|
156
|
+
// Circuit ID mapping for DOP Engine
|
|
157
|
+
const CIRCUIT_IDS = {
|
|
158
|
+
dop: 0,
|
|
159
|
+
decrypt: 1,
|
|
160
|
+
nullify: 2
|
|
161
|
+
};
|
|
162
|
+
// Configure DOP Engine to use Mopro as native prover
|
|
163
|
+
const moproNativeProver = async (circuitId, _datBuffer, zkeyBuffer, jsonInputs, progressCallback) => {
|
|
164
|
+
// Convert circuit ID to name
|
|
165
|
+
const circuitName = Object.keys(CIRCUIT_IDS).find(key => CIRCUIT_IDS[key] === circuitId) ?? `circuit-${circuitId}`;
|
|
166
|
+
// Load circuit file to device filesystem
|
|
167
|
+
const zkeyPath = await circuitLoader.loadCircuit(circuitName, new Uint8Array(zkeyBuffer));
|
|
168
|
+
// Generate proof with Mopro
|
|
169
|
+
return moproAdapter.generateProof(circuitName, zkeyPath, jsonInputs, progressCallback);
|
|
170
|
+
};
|
|
171
|
+
// Set the native prover in DOP Engine
|
|
172
|
+
prover.setNativeProverGroth16(moproNativeProver, CIRCUIT_IDS);
|
|
173
|
+
console.log('✅ Mopro prover setup complete');
|
|
174
|
+
console.log(` Using proof backend: ${proofLib}`);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
console.error('❌ Mopro prover setup failed:', error);
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
exports.setupMoproProver = setupMoproProver;
|
|
90
183
|
/**
|
|
91
184
|
* Setup Groth16 prover for React Native
|
|
92
|
-
*
|
|
185
|
+
* Tries Mopro first, falls back to checking Rapidsnark backend availability
|
|
93
186
|
*/
|
|
94
187
|
const setupReactNativeProver = async () => {
|
|
95
188
|
if (!runtime_1.isReactNative) {
|
|
96
189
|
return true; // Not in React Native, nothing to do
|
|
97
190
|
}
|
|
98
|
-
|
|
191
|
+
const support = await (0, exports.checkReactNativeProverSupport)();
|
|
192
|
+
if (support.method === 'mopro') {
|
|
193
|
+
// Try to setup Mopro
|
|
194
|
+
const moproSetup = await (0, exports.setupMoproProver)();
|
|
195
|
+
if (moproSetup) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return support.available;
|
|
99
200
|
};
|
|
100
201
|
exports.setupReactNativeProver = setupReactNativeProver;
|
|
101
202
|
/**
|
|
102
203
|
* Auto-setup prover if in React Native environment
|
|
103
|
-
* Currently just checks and warns about lack of support
|
|
104
204
|
*/
|
|
105
205
|
const autoSetupProverForReactNative = async () => {
|
|
106
206
|
if (runtime_1.isReactNative) {
|
|
@@ -108,4 +208,20 @@ const autoSetupProverForReactNative = async () => {
|
|
|
108
208
|
}
|
|
109
209
|
};
|
|
110
210
|
exports.autoSetupProverForReactNative = autoSetupProverForReactNative;
|
|
211
|
+
/**
|
|
212
|
+
* Get circuit loader instance (for manual circuit preloading)
|
|
213
|
+
*/
|
|
214
|
+
const getCircuitLoader = async () => {
|
|
215
|
+
if (!runtime_1.isReactNative || !(0, mopro_circuit_loader_1.isRNFSAvailable)()) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
return await (0, mopro_circuit_loader_1.createCircuitLoader)();
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.error('Failed to create circuit loader:', error);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
exports.getCircuitLoader = getCircuitLoader;
|
|
111
227
|
//# sourceMappingURL=react-native-prover-setup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-native-prover-setup.js","sourceRoot":"","sources":["../../../../src/services/dop/core/react-native-prover-setup.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAGH,6CAAgD;AAChD,6FAAuG;AAEvG;;;GAGG;AACI,MAAM,6BAA6B,GAAG,KAAK,IAAsB,EAAE;IACxE,IAAI,CAAC,uBAAa,EAAE;QAClB,OAAO,IAAI,CAAC,CAAC,gCAAgC;KAC9C;IAED,IAAI;QACF,mCAAmC;QACnC,MAAM,WAAW,GAAG,MAAM,IAAA,qDAAoB,GAAE,CAAC;QAEjD,IAAI,CAAC,WAAW,IAAI,CAAC,IAAA,sDAAqB,GAAE,EAAE;YAC5C,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACnE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;YAC5E,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;YAC1E,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YACvE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACrD,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;YACtE,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;YACtE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAC3E,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACpE,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACjD,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACxD,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC3C,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;YAC7D,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACtD,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC3D,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YAEnE,OAAO,KAAK,CAAC;SACd;QAED,iDAAiD;QACjD,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;QACzE,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;QAElE,OAAO,KAAK,CAAC;KAEd;IAAC,OAAO,KAAK,EAAE;QACd,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;KACd;AACH,CAAC,CAAC;AAnEW,QAAA,6BAA6B,iCAmExC;AAEF;;;GAGG;AACI,MAAM,sBAAsB,GAAG,KAAK,IAAsB,EAAE;IACjE,IAAI,CAAC,uBAAa,EAAE;QAClB,OAAO,IAAI,CAAC,CAAC,qCAAqC;KACnD;IAED,OAAO,IAAA,qCAA6B,GAAE,CAAC;AACzC,CAAC,CAAC;AANW,QAAA,sBAAsB,0BAMjC;AAEF;;;GAGG;AACI,MAAM,6BAA6B,GAAG,KAAK,IAAmB,EAAE;IACrE,IAAI,uBAAa,EAAE;QACjB,MAAM,IAAA,8BAAsB,GAAE,CAAC;KAChC;AACH,CAAC,CAAC;AAJW,QAAA,6BAA6B,iCAIxC","sourcesContent":["/**\n * React Native Prover Setup\n * \n * IMPORTANT: Direct proof generation in React Native is not currently supported by the DOP SDK.\n * \n * The DOP Engine uses SnarkJS internally which requires WebAssembly and Web Workers that\n * are not available in React Native's JavaScriptCore engine.\n * \n * Rapidsnark (@iden3/react-native-rapidsnark) is a native module for mobile proof generation,\n * but it requires a different integration approach that is not yet implemented in dop-engine-v3.\n * \n * WORKAROUNDS:\n * 1. Use a relay service that generates proofs server-side\n * 2. Use encrypted transfers only (which don't require proofs)\n * 3. Wait for DOP to release React Native-compatible proof generation\n */\n\nimport { getProver } from './prover';\nimport { isReactNative } from '../util/runtime';\nimport { initializeRapidsnark, isRapidsnarkAvailable } from '../crypto/react-native-rapidsnark-prover';\n\n/**\n * Check if proof generation is available in React Native\n * Returns false with helpful error message\n */\nexport const checkReactNativeProverSupport = async (): Promise<boolean> => {\n if (!isReactNative) {\n return true; // Not in React Native, no issue\n }\n\n try {\n // Check if Rapidsnark is available\n const initialized = await initializeRapidsnark();\n \n if (!initialized || !isRapidsnarkAvailable()) {\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.error('⚠️ REACT NATIVE PROOF GENERATION NOT SUPPORTED');\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.error('');\n console.error('The DOP SDK cannot generate zero-knowledge proofs directly');\n console.error('in React Native because SnarkJS requires WebAssembly and');\n console.error('Web Workers that are not available in JavaScriptCore.');\n console.error('');\n console.error('WORKAROUNDS:');\n console.error('');\n console.error('1. Use Relay Service (Recommended):');\n console.error(' Set up a proof generation relay service that runs');\n console.error(' Node.js and handles proof generation server-side.');\n console.error('');\n console.error('2. Use Encrypted Transfers Only:');\n console.error(' Encrypt tokens to the DOP contract (shield operations)');\n console.error(' without generating proofs for private transfers.');\n console.error('');\n console.error('3. Wait for Native Support:');\n console.error(' DOP is working on React Native-compatible proof');\n console.error(' generation using @iden3/react-native-rapidsnark.');\n console.error('');\n console.error('Operations that require proofs:');\n console.error(' - Private transfers (sendERC20Token)');\n console.error(' - Private NFT transfers');\n console.error(' - Unshield operations (decryptERC20Token)');\n console.error('');\n console.error('Operations that work without proofs:');\n console.error(' - Shield operations (encryptERC20Token)');\n console.error(' - Balance queries');\n console.error(' - Wallet creation');\n console.error(' - Transaction history');\n console.error('');\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n \n return false;\n }\n \n // Rapidsnark is available but not yet integrated\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.warn('⚠️ RAPIDSNARK DETECTED BUT NOT YET INTEGRATED');\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.warn('');\n console.warn('Rapidsnark (@iden3/react-native-rapidsnark) is installed');\n console.warn('but the DOP SDK does not yet support it automatically.');\n console.warn('');\n console.warn('This feature is under development. For now, use one of');\n console.warn('the workarounds mentioned in the documentation.');\n console.warn('');\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n \n return false;\n \n } catch (error) {\n console.error('Error checking React Native prover support:', error);\n return false;\n }\n};\n\n/**\n * Setup Groth16 prover for React Native\n * Currently logs a warning that this is not yet supported\n */\nexport const setupReactNativeProver = async (): Promise<boolean> => {\n if (!isReactNative) {\n return true; // Not in React Native, nothing to do\n }\n\n return checkReactNativeProverSupport();\n};\n\n/**\n * Auto-setup prover if in React Native environment\n * Currently just checks and warns about lack of support\n */\nexport const autoSetupProverForReactNative = async (): Promise<void> => {\n if (isReactNative) {\n await setupReactNativeProver();\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"react-native-prover-setup.js","sourceRoot":"","sources":["../../../../src/services/dop/core/react-native-prover-setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * React Native Prover Setup\n * \n * This module enables fully on-device zero-knowledge proof generation in React Native\n * using Mopro (Mobile Prover) toolkit.\n * \n * SUPPORTED APPROACHES:\n * 1. Mopro (Recommended) - Full on-device proof generation with native performance\n * 2. Backend Witness Service - Generate witness on backend, proof on device with Rapidsnark\n * 3. Encrypted Transfers Only - Shield operations without proof generation\n * \n * MOPRO INTEGRATION:\n * - Witness generation: Native C++/Rust (2-29x faster than browser)\n * - Proof generation: Native Arkworks or Rapidsnark (8-15x faster than browser)\n * - No WebAssembly required (bypasses React Native limitations)\n * - No backend service needed\n * \n * @see https://zkmopro.org/docs/intro\n * @see MOPRO_INTEGRATION_PLAN.md\n */\n\nimport { getProver, type FormattedCircuitInputsDop, type Proof } from './prover';\nimport { isReactNative } from '../util/runtime';\nimport { initializeRapidsnark, isRapidsnarkAvailable } from '../crypto/react-native-rapidsnark-prover';\nimport { \n initializeMopro, \n isMoproAvailable, \n MoproProverAdapter,\n ProofLib\n} from '../crypto/mopro-prover-adapter';\nimport { \n initializeRNFS,\n isRNFSAvailable,\n createCircuitLoader,\n type MoproCircuitLoader\n} from '../crypto/mopro-circuit-loader';\n\n/**\n * Check if proof generation is available in React Native\n * Tries Mopro first (recommended), then falls back to Rapidsnark backend approach\n */\nexport const checkReactNativeProverSupport = async (): Promise<{\n available: boolean;\n method: 'mopro' | 'rapidsnark-backend' | 'none';\n message: string;\n}> => {\n if (!isReactNative) {\n return {\n available: true,\n method: 'none',\n message: 'Not in React Native environment'\n };\n }\n\n try {\n // Try to initialize Mopro (fully on-device)\n const moproInit = await initializeMopro();\n const rnfsInit = await initializeRNFS();\n \n if (moproInit && rnfsInit && isMoproAvailable() && isRNFSAvailable()) {\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('✅ MOPRO PROOF GENERATION AVAILABLE');\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.log('');\n console.log('🚀 Fully on-device proof generation enabled via Mopro');\n console.log(' - No backend witness service needed');\n console.log(' - Native performance (8-25x faster than browser)');\n console.log(' - All DOP operations work fully on-device');\n console.log('');\n console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n \n return {\n available: true,\n method: 'mopro',\n message: 'Mopro initialized successfully'\n };\n }\n\n // Mopro not available, try Rapidsnark backend approach\n const rapidsnarkInit = await initializeRapidsnark();\n \n if (rapidsnarkInit && isRapidsnarkAvailable()) {\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.warn('⚠️ RAPIDSNARK AVAILABLE (BACKEND WITNESS REQUIRED)');\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.warn('');\n console.warn('Rapidsnark is available for proof generation, but witness');\n console.warn('calculation must be done on a backend service.');\n console.warn('');\n console.warn('For fully on-device proof generation, install Mopro:');\n console.warn(' npm install mopro-ffi react-native-fs');\n console.warn(' See: https://zkmopro.org/docs/setup/react-native-setup');\n console.warn('');\n console.warn('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n \n return {\n available: true,\n method: 'rapidsnark-backend',\n message: 'Rapidsnark available, backend witness required'\n };\n }\n\n // Neither Mopro nor Rapidsnark available\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.error('⚠️ REACT NATIVE PROOF GENERATION NOT AVAILABLE');\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n console.error('');\n console.error('The DOP SDK cannot generate zero-knowledge proofs in');\n console.error('React Native because SnarkJS requires WebAssembly.');\n console.error('');\n console.error('RECOMMENDED SOLUTION:');\n console.error('');\n console.error('Install Mopro for fully on-device proof generation:');\n console.error(' npm install mopro-ffi react-native-fs');\n console.error(' Setup guide: https://zkmopro.org/docs/setup/react-native-setup');\n console.error('');\n console.error('Benefits:');\n console.error(' ✅ No backend service needed');\n console.error(' ✅ 8-25x faster than browser');\n console.error(' ✅ Native iOS/Android performance');\n console.error(' ✅ Privacy-preserving (no data leaves device)');\n console.error('');\n console.error('ALTERNATIVE SOLUTIONS:');\n console.error('');\n console.error('1. Backend Witness Service:');\n console.error(' Install @iden3/react-native-rapidsnark for proof generation');\n console.error(' Set up backend service for witness calculation');\n console.error('');\n console.error('2. Encrypted Transfers Only:');\n console.error(' Shield operations work without proof generation');\n console.error('');\n console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n \n return {\n available: false,\n method: 'none',\n message: 'No proof generation method available'\n };\n \n } catch (error) {\n console.error('Error checking React Native prover support:', error);\n return {\n available: false,\n method: 'none',\n message: `Error: ${error instanceof Error ? error.message : String(error)}`\n };\n }\n};\n\n/**\n * Setup Mopro prover for React Native\n * Configures DOP Engine to use Mopro for fully on-device proof generation\n * \n * @param useRapidsnark - Use Rapidsnark backend instead of Arkworks (default: false)\n * @returns true if setup successful\n */\nexport const setupMoproProver = async (useRapidsnark = false): Promise<boolean> => {\n if (!isReactNative) {\n return true;\n }\n\n try {\n // Initialize Mopro and RNFS\n const moproInit = await initializeMopro();\n const rnfsInit = await initializeRNFS();\n\n if (!moproInit || !rnfsInit) {\n console.error('❌ Failed to initialize Mopro or RNFS');\n return false;\n }\n\n console.log('🔧 Setting up Mopro prover for DOP Engine...');\n\n // Create Mopro adapter\n const proofLib = useRapidsnark ? ProofLib.Rapidsnark : ProofLib.Arkworks;\n const moproAdapter = new MoproProverAdapter(proofLib);\n\n // Create circuit loader\n const circuitLoader = await createCircuitLoader();\n\n // Get DOP Engine prover instance\n const prover = getProver();\n\n // Circuit ID mapping for DOP Engine\n const CIRCUIT_IDS = {\n dop: 0,\n decrypt: 1,\n nullify: 2\n };\n\n // Configure DOP Engine to use Mopro as native prover\n const moproNativeProver = async (\n circuitId: number,\n _datBuffer: Buffer,\n zkeyBuffer: Buffer,\n jsonInputs: FormattedCircuitInputsDop,\n progressCallback?: (progress: number) => void\n ): Promise<Proof> => {\n // Convert circuit ID to name\n const circuitName: string = Object.keys(CIRCUIT_IDS).find(\n key => CIRCUIT_IDS[key as keyof typeof CIRCUIT_IDS] === circuitId\n ) ?? `circuit-${circuitId}`;\n\n // Load circuit file to device filesystem\n const zkeyPath = await circuitLoader.loadCircuit(\n circuitName,\n new Uint8Array(zkeyBuffer)\n );\n\n // Generate proof with Mopro\n return moproAdapter.generateProof(\n circuitName,\n zkeyPath,\n jsonInputs,\n progressCallback\n );\n };\n\n // Set the native prover in DOP Engine\n prover.setNativeProverGroth16(moproNativeProver as any, CIRCUIT_IDS);\n \n console.log('✅ Mopro prover setup complete');\n console.log(` Using proof backend: ${proofLib}`);\n \n return true;\n\n } catch (error) {\n console.error('❌ Mopro prover setup failed:', error);\n return false;\n }\n};\n\n/**\n * Setup Groth16 prover for React Native\n * Tries Mopro first, falls back to checking Rapidsnark backend availability\n */\nexport const setupReactNativeProver = async (): Promise<boolean> => {\n if (!isReactNative) {\n return true; // Not in React Native, nothing to do\n }\n\n const support = await checkReactNativeProverSupport();\n \n if (support.method === 'mopro') {\n // Try to setup Mopro\n const moproSetup = await setupMoproProver();\n if (moproSetup) {\n return true;\n }\n }\n\n return support.available;\n};\n\n/**\n * Auto-setup prover if in React Native environment\n */\nexport const autoSetupProverForReactNative = async (): Promise<void> => {\n if (isReactNative) {\n await setupReactNativeProver();\n }\n};\n\n/**\n * Get circuit loader instance (for manual circuit preloading)\n */\nexport const getCircuitLoader = async (): Promise<MoproCircuitLoader | null> => {\n if (!isReactNative || !isRNFSAvailable()) {\n return null;\n }\n\n try {\n return await createCircuitLoader();\n } catch (error) {\n console.error('Failed to create circuit loader:', error);\n return null;\n }\n};\n"]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mopro Circuit Loader for React Native
|
|
3
|
+
*
|
|
4
|
+
* This module handles loading and caching DOP circuit files (zkey) on
|
|
5
|
+
* the React Native device filesystem. Circuit files are downloaded from
|
|
6
|
+
* IPFS by the artifact downloader and then saved to the app's document
|
|
7
|
+
* directory for use by Mopro's native proof generation.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Caches circuit file paths to avoid repeated file operations
|
|
11
|
+
* - Handles circuit file compression (brotli)
|
|
12
|
+
* - Preloads circuits at app startup for faster proof generation
|
|
13
|
+
* - Manages cleanup of old circuit files
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Circuit file information
|
|
17
|
+
*/
|
|
18
|
+
interface CircuitInfo {
|
|
19
|
+
circuitId: string;
|
|
20
|
+
zkeyPath: string;
|
|
21
|
+
fileSize: number;
|
|
22
|
+
loadedAt: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Initialize React Native filesystem module
|
|
26
|
+
*/
|
|
27
|
+
export declare const initializeRNFS: () => Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Check if RNFS is available
|
|
30
|
+
*/
|
|
31
|
+
export declare const isRNFSAvailable: () => boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Mopro Circuit Loader Class
|
|
34
|
+
*
|
|
35
|
+
* Manages circuit files on the React Native filesystem
|
|
36
|
+
*/
|
|
37
|
+
export declare class MoproCircuitLoader {
|
|
38
|
+
private circuitCache;
|
|
39
|
+
private circuitsDir;
|
|
40
|
+
private initialized;
|
|
41
|
+
constructor();
|
|
42
|
+
/**
|
|
43
|
+
* Initialize the circuit loader
|
|
44
|
+
* Creates the circuits directory if it doesn't exist
|
|
45
|
+
*/
|
|
46
|
+
initialize(): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Load a circuit file from buffer and save to filesystem
|
|
49
|
+
*
|
|
50
|
+
* @param circuitId - Circuit identifier (e.g., '1x2', '2x2')
|
|
51
|
+
* @param zkeyBuffer - The zkey file buffer
|
|
52
|
+
* @returns Path to the saved zkey file
|
|
53
|
+
*/
|
|
54
|
+
loadCircuit(circuitId: string, zkeyBuffer: Uint8Array): Promise<string>;
|
|
55
|
+
/**
|
|
56
|
+
* Preload multiple circuits at app startup
|
|
57
|
+
* This prevents delays during first proof generation
|
|
58
|
+
*
|
|
59
|
+
* @param circuits - Map of circuitId to zkeyBuffer
|
|
60
|
+
*/
|
|
61
|
+
preloadCircuits(circuits: Map<string, Uint8Array>): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Get cached circuit info
|
|
64
|
+
*/
|
|
65
|
+
getCircuitInfo(circuitId: string): CircuitInfo | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Clear all cached circuits from memory
|
|
68
|
+
* (Files remain on disk)
|
|
69
|
+
*/
|
|
70
|
+
clearCache(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Delete circuit files from filesystem
|
|
73
|
+
*
|
|
74
|
+
* @param circuitIds - Array of circuit IDs to delete, or empty to delete all
|
|
75
|
+
*/
|
|
76
|
+
deleteCircuits(circuitIds?: string[]): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Get total size of cached circuits
|
|
79
|
+
*/
|
|
80
|
+
getTotalCacheSize(): number;
|
|
81
|
+
/**
|
|
82
|
+
* Get cache statistics
|
|
83
|
+
*/
|
|
84
|
+
getCacheStats(): {
|
|
85
|
+
circuitCount: number;
|
|
86
|
+
totalSize: string;
|
|
87
|
+
circuits: CircuitInfo[];
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Convert Uint8Array to base64 string
|
|
91
|
+
*/
|
|
92
|
+
private static bufferToBase64;
|
|
93
|
+
/**
|
|
94
|
+
* Format file size for human readability
|
|
95
|
+
*/
|
|
96
|
+
private static formatFileSize;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a circuit loader instance
|
|
100
|
+
* Automatically initializes RNFS if not already done
|
|
101
|
+
*/
|
|
102
|
+
export declare const createCircuitLoader: () => Promise<MoproCircuitLoader>;
|
|
103
|
+
export {};
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mopro Circuit Loader for React Native
|
|
4
|
+
*
|
|
5
|
+
* This module handles loading and caching DOP circuit files (zkey) on
|
|
6
|
+
* the React Native device filesystem. Circuit files are downloaded from
|
|
7
|
+
* IPFS by the artifact downloader and then saved to the app's document
|
|
8
|
+
* directory for use by Mopro's native proof generation.
|
|
9
|
+
*
|
|
10
|
+
* Features:
|
|
11
|
+
* - Caches circuit file paths to avoid repeated file operations
|
|
12
|
+
* - Handles circuit file compression (brotli)
|
|
13
|
+
* - Preloads circuits at app startup for faster proof generation
|
|
14
|
+
* - Manages cleanup of old circuit files
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createCircuitLoader = exports.MoproCircuitLoader = exports.isRNFSAvailable = exports.initializeRNFS = void 0;
|
|
41
|
+
const runtime_1 = require("../util/runtime");
|
|
42
|
+
let rnfsModule = null;
|
|
43
|
+
/**
|
|
44
|
+
* Initialize React Native filesystem module
|
|
45
|
+
*/
|
|
46
|
+
const initializeRNFS = async () => {
|
|
47
|
+
var _a;
|
|
48
|
+
if (!runtime_1.isReactNative) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const moduleName = 'react-native-fs';
|
|
53
|
+
const rnfsImport = await (_a = moduleName, Promise.resolve().then(() => __importStar(require(_a))));
|
|
54
|
+
rnfsModule = (rnfsImport.default ?? rnfsImport);
|
|
55
|
+
console.log('📁 React Native FS initialized');
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.warn('⚠️ react-native-fs not available:', error);
|
|
60
|
+
console.log('💡 Install react-native-fs: npm install react-native-fs');
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
exports.initializeRNFS = initializeRNFS;
|
|
65
|
+
/**
|
|
66
|
+
* Check if RNFS is available
|
|
67
|
+
*/
|
|
68
|
+
const isRNFSAvailable = () => {
|
|
69
|
+
return runtime_1.isReactNative && rnfsModule !== null;
|
|
70
|
+
};
|
|
71
|
+
exports.isRNFSAvailable = isRNFSAvailable;
|
|
72
|
+
/**
|
|
73
|
+
* Mopro Circuit Loader Class
|
|
74
|
+
*
|
|
75
|
+
* Manages circuit files on the React Native filesystem
|
|
76
|
+
*/
|
|
77
|
+
class MoproCircuitLoader {
|
|
78
|
+
circuitCache = new Map();
|
|
79
|
+
circuitsDir;
|
|
80
|
+
initialized = false;
|
|
81
|
+
constructor() {
|
|
82
|
+
if (!(0, exports.isRNFSAvailable)() || !rnfsModule) {
|
|
83
|
+
throw new Error('react-native-fs not available. Install it with: npm install react-native-fs');
|
|
84
|
+
}
|
|
85
|
+
this.circuitsDir = `${rnfsModule.DocumentDirectoryPath}/dop-circuits`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Initialize the circuit loader
|
|
89
|
+
* Creates the circuits directory if it doesn't exist
|
|
90
|
+
*/
|
|
91
|
+
async initialize() {
|
|
92
|
+
if (this.initialized || !rnfsModule) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
console.log('📂 Initializing Mopro circuit loader...');
|
|
97
|
+
console.log(` Circuits directory: ${this.circuitsDir}`);
|
|
98
|
+
// Create circuits directory
|
|
99
|
+
await rnfsModule.mkdir(this.circuitsDir, {
|
|
100
|
+
NSURLIsExcludedFromBackupKey: true // Don't backup to iCloud
|
|
101
|
+
});
|
|
102
|
+
this.initialized = true;
|
|
103
|
+
console.log('✅ Circuit loader initialized');
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
// Directory might already exist, that's okay
|
|
107
|
+
if (error instanceof Error && error.message.includes('already exists')) {
|
|
108
|
+
this.initialized = true;
|
|
109
|
+
console.log('✅ Circuit loader initialized (directory exists)');
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.error('❌ Failed to initialize circuit loader:', error);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Load a circuit file from buffer and save to filesystem
|
|
119
|
+
*
|
|
120
|
+
* @param circuitId - Circuit identifier (e.g., '1x2', '2x2')
|
|
121
|
+
* @param zkeyBuffer - The zkey file buffer
|
|
122
|
+
* @returns Path to the saved zkey file
|
|
123
|
+
*/
|
|
124
|
+
async loadCircuit(circuitId, zkeyBuffer) {
|
|
125
|
+
if (!rnfsModule) {
|
|
126
|
+
throw new Error('react-native-fs not initialized');
|
|
127
|
+
}
|
|
128
|
+
await this.initialize();
|
|
129
|
+
// Check if circuit is already cached
|
|
130
|
+
const cached = this.circuitCache.get(circuitId);
|
|
131
|
+
if (cached) {
|
|
132
|
+
// Verify file still exists
|
|
133
|
+
const exists = await rnfsModule.exists(cached.zkeyPath);
|
|
134
|
+
if (exists) {
|
|
135
|
+
console.log(`📦 Using cached circuit: ${circuitId}`);
|
|
136
|
+
return cached.zkeyPath;
|
|
137
|
+
}
|
|
138
|
+
// File was deleted, remove from cache
|
|
139
|
+
this.circuitCache.delete(circuitId);
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
console.log(`💾 Loading circuit to filesystem: ${circuitId}`);
|
|
143
|
+
const startTime = Date.now();
|
|
144
|
+
// Generate file path
|
|
145
|
+
const zkeyPath = `${this.circuitsDir}/${circuitId}.zkey`;
|
|
146
|
+
// Convert buffer to base64 for react-native-fs
|
|
147
|
+
const base64Data = MoproCircuitLoader.bufferToBase64(zkeyBuffer);
|
|
148
|
+
// Write to file
|
|
149
|
+
await rnfsModule.writeFile(zkeyPath, base64Data, 'base64');
|
|
150
|
+
// Verify file was written
|
|
151
|
+
const stat = await rnfsModule.stat(zkeyPath);
|
|
152
|
+
const fileSize = stat.size;
|
|
153
|
+
// Cache the circuit info
|
|
154
|
+
const circuitInfo = {
|
|
155
|
+
circuitId,
|
|
156
|
+
zkeyPath,
|
|
157
|
+
fileSize,
|
|
158
|
+
loadedAt: Date.now()
|
|
159
|
+
};
|
|
160
|
+
this.circuitCache.set(circuitId, circuitInfo);
|
|
161
|
+
const elapsedTime = Date.now() - startTime;
|
|
162
|
+
console.log(`✅ Circuit loaded successfully in ${elapsedTime}ms`);
|
|
163
|
+
// eslint-disable-next-line no-console
|
|
164
|
+
console.log(` File size: ${MoproCircuitLoader.formatFileSize(fileSize)}`);
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.log(` Path: ${zkeyPath}`);
|
|
167
|
+
return zkeyPath;
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error(`❌ Failed to load circuit ${circuitId}:`, error);
|
|
171
|
+
throw new Error(`Circuit loading failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Preload multiple circuits at app startup
|
|
176
|
+
* This prevents delays during first proof generation
|
|
177
|
+
*
|
|
178
|
+
* @param circuits - Map of circuitId to zkeyBuffer
|
|
179
|
+
*/
|
|
180
|
+
async preloadCircuits(circuits) {
|
|
181
|
+
console.log(`🚀 Preloading ${circuits.size} circuits...`);
|
|
182
|
+
const startTime = Date.now();
|
|
183
|
+
const loadPromises = Array.from(circuits.entries()).map(([circuitId, zkeyBuffer]) => this.loadCircuit(circuitId, zkeyBuffer));
|
|
184
|
+
try {
|
|
185
|
+
await Promise.all(loadPromises);
|
|
186
|
+
const elapsedTime = Date.now() - startTime;
|
|
187
|
+
console.log(`✅ Preloaded ${circuits.size} circuits in ${elapsedTime}ms`);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
console.error('❌ Failed to preload circuits:', error);
|
|
191
|
+
throw error;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get cached circuit info
|
|
196
|
+
*/
|
|
197
|
+
getCircuitInfo(circuitId) {
|
|
198
|
+
return this.circuitCache.get(circuitId);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Clear all cached circuits from memory
|
|
202
|
+
* (Files remain on disk)
|
|
203
|
+
*/
|
|
204
|
+
clearCache() {
|
|
205
|
+
console.log(`🗑️ Clearing circuit cache (${this.circuitCache.size} entries)`);
|
|
206
|
+
this.circuitCache.clear();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Delete circuit files from filesystem
|
|
210
|
+
*
|
|
211
|
+
* @param circuitIds - Array of circuit IDs to delete, or empty to delete all
|
|
212
|
+
*/
|
|
213
|
+
async deleteCircuits(circuitIds) {
|
|
214
|
+
if (!rnfsModule) {
|
|
215
|
+
throw new Error('react-native-fs not initialized');
|
|
216
|
+
}
|
|
217
|
+
const toDelete = circuitIds || Array.from(this.circuitCache.keys());
|
|
218
|
+
// eslint-disable-next-line no-console
|
|
219
|
+
console.log(`🗑️ Deleting ${toDelete.length} circuit files...`);
|
|
220
|
+
const rnfs = rnfsModule; // Capture for use in async callbacks
|
|
221
|
+
const deletePromises = toDelete.map(async (circuitId) => {
|
|
222
|
+
try {
|
|
223
|
+
const cached = this.circuitCache.get(circuitId);
|
|
224
|
+
if (cached) {
|
|
225
|
+
const exists = await rnfs.exists(cached.zkeyPath);
|
|
226
|
+
if (exists) {
|
|
227
|
+
await rnfs.unlink(cached.zkeyPath);
|
|
228
|
+
// eslint-disable-next-line no-console
|
|
229
|
+
console.log(` Deleted: ${circuitId}`);
|
|
230
|
+
}
|
|
231
|
+
this.circuitCache.delete(circuitId);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
// eslint-disable-next-line no-console
|
|
236
|
+
console.warn(` Failed to delete ${circuitId}:`, error);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
await Promise.all(deletePromises);
|
|
240
|
+
// eslint-disable-next-line no-console
|
|
241
|
+
console.log('✅ Circuit deletion complete');
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get total size of cached circuits
|
|
245
|
+
*/
|
|
246
|
+
getTotalCacheSize() {
|
|
247
|
+
let totalSize = 0;
|
|
248
|
+
for (const info of this.circuitCache.values()) {
|
|
249
|
+
totalSize += info.fileSize;
|
|
250
|
+
}
|
|
251
|
+
return totalSize;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get cache statistics
|
|
255
|
+
*/
|
|
256
|
+
getCacheStats() {
|
|
257
|
+
const circuits = Array.from(this.circuitCache.values());
|
|
258
|
+
return {
|
|
259
|
+
circuitCount: circuits.length,
|
|
260
|
+
totalSize: MoproCircuitLoader.formatFileSize(this.getTotalCacheSize()),
|
|
261
|
+
circuits
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Convert Uint8Array to base64 string
|
|
266
|
+
*/
|
|
267
|
+
static bufferToBase64(buffer) {
|
|
268
|
+
if (typeof Buffer !== 'undefined') {
|
|
269
|
+
return Buffer.from(buffer).toString('base64');
|
|
270
|
+
}
|
|
271
|
+
// Fallback for environments without Buffer
|
|
272
|
+
let binary = '';
|
|
273
|
+
for (let i = 0; i < buffer.length; i += 1) {
|
|
274
|
+
binary += String.fromCharCode(buffer[i]);
|
|
275
|
+
}
|
|
276
|
+
return btoa(binary);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Format file size for human readability
|
|
280
|
+
*/
|
|
281
|
+
static formatFileSize(bytes) {
|
|
282
|
+
if (bytes < 1024) {
|
|
283
|
+
return `${bytes} B`;
|
|
284
|
+
}
|
|
285
|
+
if (bytes < 1024 * 1024) {
|
|
286
|
+
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
287
|
+
}
|
|
288
|
+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
exports.MoproCircuitLoader = MoproCircuitLoader;
|
|
292
|
+
/**
|
|
293
|
+
* Create a circuit loader instance
|
|
294
|
+
* Automatically initializes RNFS if not already done
|
|
295
|
+
*/
|
|
296
|
+
const createCircuitLoader = async () => {
|
|
297
|
+
if (!(0, exports.isRNFSAvailable)()) {
|
|
298
|
+
const initialized = await (0, exports.initializeRNFS)();
|
|
299
|
+
if (!initialized) {
|
|
300
|
+
throw new Error('Failed to initialize react-native-fs. Make sure it is installed and linked properly.');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
const loader = new MoproCircuitLoader();
|
|
304
|
+
await loader.initialize();
|
|
305
|
+
return loader;
|
|
306
|
+
};
|
|
307
|
+
exports.createCircuitLoader = createCircuitLoader;
|
|
308
|
+
//# sourceMappingURL=mopro-circuit-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mopro-circuit-loader.js","sourceRoot":"","sources":["../../../../src/services/dop/crypto/mopro-circuit-loader.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mopro Circuit Loader for React Native\n * \n * This module handles loading and caching DOP circuit files (zkey) on\n * the React Native device filesystem. Circuit files are downloaded from\n * IPFS by the artifact downloader and then saved to the app's document\n * directory for use by Mopro's native proof generation.\n * \n * Features:\n * - Caches circuit file paths to avoid repeated file operations\n * - Handles circuit file compression (brotli)\n * - Preloads circuits at app startup for faster proof generation\n * - Manages cleanup of old circuit files\n */\n\nimport { isReactNative } from '../util/runtime';\n\n/**\n * Circuit file information\n */\ninterface CircuitInfo {\n circuitId: string;\n zkeyPath: string;\n fileSize: number;\n loadedAt: number;\n}\n\n/**\n * React Native filesystem interface (react-native-fs)\n * Declared as interface to avoid compilation errors when not installed\n */\ninterface ReactNativeFS {\n DocumentDirectoryPath: string;\n mkdir: (path: string, options?: { NSURLIsExcludedFromBackupKey?: boolean }) => Promise<void>;\n writeFile: (path: string, contents: 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 stat: (path: string) => Promise<{ size: number }>;\n}\n\nlet rnfsModule: ReactNativeFS | null = null;\n\n/**\n * Initialize React Native filesystem module\n */\nexport const initializeRNFS = async (): Promise<boolean> => {\n if (!isReactNative) {\n return false;\n }\n\n try {\n const moduleName = 'react-native-fs';\n const rnfsImport = await import(moduleName);\n rnfsModule = (rnfsImport.default ?? rnfsImport) as ReactNativeFS;\n \n console.log('📁 React Native FS initialized');\n return true;\n } catch (error) {\n console.warn('⚠️ react-native-fs not available:', error);\n console.log('💡 Install react-native-fs: npm install react-native-fs');\n return false;\n }\n};\n\n/**\n * Check if RNFS is available\n */\nexport const isRNFSAvailable = (): boolean => {\n return isReactNative && rnfsModule !== null;\n};\n\n/**\n * Mopro Circuit Loader Class\n * \n * Manages circuit files on the React Native filesystem\n */\nexport class MoproCircuitLoader {\n private circuitCache: Map<string, CircuitInfo> = new Map();\n private circuitsDir: string;\n private initialized = false;\n\n constructor() {\n if (!isRNFSAvailable() || !rnfsModule) {\n throw new Error(\n 'react-native-fs not available. Install it with: npm install react-native-fs'\n );\n }\n \n this.circuitsDir = `${rnfsModule.DocumentDirectoryPath}/dop-circuits`;\n }\n\n /**\n * Initialize the circuit loader\n * Creates the circuits directory if it doesn't exist\n */\n async initialize(): Promise<void> {\n if (this.initialized || !rnfsModule) {\n return;\n }\n\n try {\n console.log('📂 Initializing Mopro circuit loader...');\n console.log(` Circuits directory: ${this.circuitsDir}`);\n\n // Create circuits directory\n await rnfsModule.mkdir(this.circuitsDir, {\n NSURLIsExcludedFromBackupKey: true // Don't backup to iCloud\n });\n\n this.initialized = true;\n console.log('✅ Circuit loader initialized');\n } catch (error) {\n // Directory might already exist, that's okay\n if (error instanceof Error && error.message.includes('already exists')) {\n this.initialized = true;\n console.log('✅ Circuit loader initialized (directory exists)');\n } else {\n console.error('❌ Failed to initialize circuit loader:', error);\n throw error;\n }\n }\n }\n\n /**\n * Load a circuit file from buffer and save to filesystem\n * \n * @param circuitId - Circuit identifier (e.g., '1x2', '2x2')\n * @param zkeyBuffer - The zkey file buffer\n * @returns Path to the saved zkey file\n */\n async loadCircuit(\n circuitId: string,\n zkeyBuffer: Uint8Array\n ): Promise<string> {\n if (!rnfsModule) {\n throw new Error('react-native-fs not initialized');\n }\n\n await this.initialize();\n\n // Check if circuit is already cached\n const cached = this.circuitCache.get(circuitId);\n if (cached) {\n // Verify file still exists\n const exists = await rnfsModule.exists(cached.zkeyPath);\n if (exists) {\n console.log(`📦 Using cached circuit: ${circuitId}`);\n return cached.zkeyPath;\n }\n // File was deleted, remove from cache\n this.circuitCache.delete(circuitId);\n }\n\n try {\n console.log(`💾 Loading circuit to filesystem: ${circuitId}`);\n const startTime = Date.now();\n\n // Generate file path\n const zkeyPath = `${this.circuitsDir}/${circuitId}.zkey`;\n\n // Convert buffer to base64 for react-native-fs\n const base64Data = MoproCircuitLoader.bufferToBase64(zkeyBuffer);\n\n // Write to file\n await rnfsModule.writeFile(zkeyPath, base64Data, 'base64');\n\n // Verify file was written\n const stat = await rnfsModule.stat(zkeyPath);\n const fileSize = stat.size;\n\n // Cache the circuit info\n const circuitInfo: CircuitInfo = {\n circuitId,\n zkeyPath,\n fileSize,\n loadedAt: Date.now()\n };\n this.circuitCache.set(circuitId, circuitInfo);\n\n const elapsedTime = Date.now() - startTime;\n console.log(`✅ Circuit loaded successfully in ${elapsedTime}ms`);\n // eslint-disable-next-line no-console\n console.log(` File size: ${MoproCircuitLoader.formatFileSize(fileSize)}`);\n // eslint-disable-next-line no-console\n console.log(` Path: ${zkeyPath}`);\n\n return zkeyPath;\n\n } catch (error) {\n console.error(`❌ Failed to load circuit ${circuitId}:`, error);\n throw new Error(\n `Circuit loading failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Preload multiple circuits at app startup\n * This prevents delays during first proof generation\n * \n * @param circuits - Map of circuitId to zkeyBuffer\n */\n async preloadCircuits(\n circuits: Map<string, Uint8Array>\n ): Promise<void> {\n console.log(`🚀 Preloading ${circuits.size} circuits...`);\n const startTime = Date.now();\n\n const loadPromises = Array.from(circuits.entries()).map(\n ([circuitId, zkeyBuffer]) => this.loadCircuit(circuitId, zkeyBuffer)\n );\n\n try {\n await Promise.all(loadPromises);\n const elapsedTime = Date.now() - startTime;\n console.log(`✅ Preloaded ${circuits.size} circuits in ${elapsedTime}ms`);\n } catch (error) {\n console.error('❌ Failed to preload circuits:', error);\n throw error;\n }\n }\n\n /**\n * Get cached circuit info\n */\n getCircuitInfo(circuitId: string): CircuitInfo | undefined {\n return this.circuitCache.get(circuitId);\n }\n\n /**\n * Clear all cached circuits from memory\n * (Files remain on disk)\n */\n clearCache(): void {\n console.log(`🗑️ Clearing circuit cache (${this.circuitCache.size} entries)`);\n this.circuitCache.clear();\n }\n\n /**\n * Delete circuit files from filesystem\n * \n * @param circuitIds - Array of circuit IDs to delete, or empty to delete all\n */\n async deleteCircuits(circuitIds?: string[]): Promise<void> {\n if (!rnfsModule) {\n throw new Error('react-native-fs not initialized');\n }\n\n const toDelete = circuitIds || Array.from(this.circuitCache.keys());\n // eslint-disable-next-line no-console\n console.log(`🗑️ Deleting ${toDelete.length} circuit files...`);\n\n const rnfs = rnfsModule; // Capture for use in async callbacks\n const deletePromises = toDelete.map(async (circuitId) => {\n try {\n const cached = this.circuitCache.get(circuitId);\n if (cached) {\n const exists = await rnfs.exists(cached.zkeyPath);\n if (exists) {\n await rnfs.unlink(cached.zkeyPath);\n // eslint-disable-next-line no-console\n console.log(` Deleted: ${circuitId}`);\n }\n this.circuitCache.delete(circuitId);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn(` Failed to delete ${circuitId}:`, error);\n }\n });\n \n await Promise.all(deletePromises);\n\n // eslint-disable-next-line no-console\n console.log('✅ Circuit deletion complete');\n }\n\n /**\n * Get total size of cached circuits\n */\n getTotalCacheSize(): number {\n let totalSize = 0;\n for (const info of this.circuitCache.values()) {\n totalSize += info.fileSize;\n }\n return totalSize;\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats(): {\n circuitCount: number;\n totalSize: string;\n circuits: CircuitInfo[];\n } {\n const circuits = Array.from(this.circuitCache.values());\n return {\n circuitCount: circuits.length,\n totalSize: MoproCircuitLoader.formatFileSize(this.getTotalCacheSize()),\n circuits\n };\n }\n\n /**\n * Convert Uint8Array to base64 string\n */\n private static bufferToBase64(buffer: Uint8Array): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(buffer).toString('base64');\n }\n\n // Fallback for environments without Buffer\n let binary = '';\n for (let i = 0; i < buffer.length; i += 1) {\n binary += String.fromCharCode(buffer[i]);\n }\n return btoa(binary);\n }\n\n /**\n * Format file size for human readability\n */\n private static formatFileSize(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(2)} KB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;\n }\n}\n\n/**\n * Create a circuit loader instance\n * Automatically initializes RNFS if not already done\n */\nexport const createCircuitLoader = async (): Promise<MoproCircuitLoader> => {\n if (!isRNFSAvailable()) {\n const initialized = await initializeRNFS();\n if (!initialized) {\n throw new Error(\n 'Failed to initialize react-native-fs. Make sure it is installed and linked properly.'\n );\n }\n }\n\n const loader = new MoproCircuitLoader();\n await loader.initialize();\n return loader;\n};\n"]}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mopro Prover Adapter for React Native
|
|
3
|
+
*
|
|
4
|
+
* This adapter enables fully on-device zero-knowledge proof generation
|
|
5
|
+
* using the Mopro (Mobile Prover) toolkit, eliminating the need for
|
|
6
|
+
* backend witness generation services.
|
|
7
|
+
*
|
|
8
|
+
* Mopro provides native witness calculation and proof generation through
|
|
9
|
+
* Rust FFI bindings, bypassing React Native's WebAssembly limitations.
|
|
10
|
+
*
|
|
11
|
+
* Performance Benefits:
|
|
12
|
+
* - Witness generation: 2-29x faster than browser SnarkJS
|
|
13
|
+
* - Proof generation: 8-15x faster than browser SnarkJS
|
|
14
|
+
* - Native iOS/Android performance
|
|
15
|
+
* - No network calls required
|
|
16
|
+
*
|
|
17
|
+
* @see https://zkmopro.org/docs/intro
|
|
18
|
+
*/
|
|
19
|
+
import type { FormattedCircuitInputsDop, Proof } from 'dop-engine-v3';
|
|
20
|
+
/**
|
|
21
|
+
* Mopro CircomProofResult structure
|
|
22
|
+
* This is the proof format returned by mopro's generateCircomProof
|
|
23
|
+
*/
|
|
24
|
+
interface MoproCircomProofResult {
|
|
25
|
+
proof: {
|
|
26
|
+
a: string[];
|
|
27
|
+
b: string[][];
|
|
28
|
+
c: string[];
|
|
29
|
+
};
|
|
30
|
+
pub_signals: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Mopro ProofLib enum for selecting proof backend
|
|
34
|
+
*/
|
|
35
|
+
declare enum ProofLib {
|
|
36
|
+
Arkworks = "Arkworks",
|
|
37
|
+
Rapidsnark = "Rapidsnark"
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize Mopro module
|
|
41
|
+
* Dynamically imports mopro-ffi to avoid compilation errors when not installed
|
|
42
|
+
*/
|
|
43
|
+
export declare const initializeMopro: () => Promise<boolean>;
|
|
44
|
+
/**
|
|
45
|
+
* Check if Mopro is available and initialized
|
|
46
|
+
*/
|
|
47
|
+
export declare const isMoproAvailable: () => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Mopro Prover Adapter Class
|
|
50
|
+
*
|
|
51
|
+
* Provides a unified interface for generating proofs with Mopro
|
|
52
|
+
* that is compatible with DOP Engine's proof format.
|
|
53
|
+
*/
|
|
54
|
+
export declare class MoproProverAdapter {
|
|
55
|
+
private proofLib;
|
|
56
|
+
constructor(proofLib?: ProofLib);
|
|
57
|
+
/**
|
|
58
|
+
* Generate a zero-knowledge proof using Mopro
|
|
59
|
+
*
|
|
60
|
+
* @param circuitId - Circuit identifier for logging/debugging
|
|
61
|
+
* @param zkeyPath - Path to the zkey file on device filesystem
|
|
62
|
+
* @param jsonInputs - Circuit inputs in JSON format
|
|
63
|
+
* @param progressCallback - Optional progress callback (0-100)
|
|
64
|
+
* @returns DOP Engine compatible proof object
|
|
65
|
+
*/
|
|
66
|
+
generateProof(circuitId: string, zkeyPath: string, jsonInputs: FormattedCircuitInputsDop, progressCallback?: (progress: number) => void): Promise<Proof>;
|
|
67
|
+
/**
|
|
68
|
+
* Verify a proof using Mopro (optional, for debugging)
|
|
69
|
+
*
|
|
70
|
+
* @param zkeyPath - Path to the zkey file
|
|
71
|
+
* @param proof - The proof to verify
|
|
72
|
+
* @returns true if proof is valid
|
|
73
|
+
*/
|
|
74
|
+
verifyProof(zkeyPath: string, proof: MoproCircomProofResult): Promise<boolean>;
|
|
75
|
+
/**
|
|
76
|
+
* Convert Mopro proof format to DOP Engine format
|
|
77
|
+
*
|
|
78
|
+
* Mopro format:
|
|
79
|
+
* {
|
|
80
|
+
* proof: { a: [string, string], b: [[string, string], [string, string]], c: [string, string] },
|
|
81
|
+
* pub_signals: string[]
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* DOP Engine format:
|
|
85
|
+
* {
|
|
86
|
+
* pi_a: [string, string],
|
|
87
|
+
* pi_b: [[string, string], [string, string]],
|
|
88
|
+
* pi_c: [string, string]
|
|
89
|
+
* }
|
|
90
|
+
*
|
|
91
|
+
* Note: Public signals are handled separately by DOP Engine
|
|
92
|
+
*/
|
|
93
|
+
private static convertMoproProofToDopFormat;
|
|
94
|
+
/**
|
|
95
|
+
* Get public signals from Mopro proof result
|
|
96
|
+
* DOP Engine may need these separately
|
|
97
|
+
*/
|
|
98
|
+
static getPublicSignals(moproResult: MoproCircomProofResult): string[];
|
|
99
|
+
/**
|
|
100
|
+
* Set the proof backend (Arkworks or Rapidsnark)
|
|
101
|
+
*
|
|
102
|
+
* Arkworks: Pure Rust implementation, consistent performance
|
|
103
|
+
* Rapidsnark: C++ optimized, potentially faster on some devices
|
|
104
|
+
*/
|
|
105
|
+
setProofLib(proofLib: ProofLib): void;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Export ProofLib enum for external use
|
|
109
|
+
*/
|
|
110
|
+
export { ProofLib };
|
|
111
|
+
/**
|
|
112
|
+
* Create a configured Mopro prover adapter
|
|
113
|
+
*
|
|
114
|
+
* @param useRapidsnark - Use Rapidsnark backend instead of Arkworks
|
|
115
|
+
* @returns Configured MoproProverAdapter instance
|
|
116
|
+
*/
|
|
117
|
+
export declare const createMoproProver: (useRapidsnark?: boolean) => MoproProverAdapter;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Mopro Prover Adapter for React Native
|
|
4
|
+
*
|
|
5
|
+
* This adapter enables fully on-device zero-knowledge proof generation
|
|
6
|
+
* using the Mopro (Mobile Prover) toolkit, eliminating the need for
|
|
7
|
+
* backend witness generation services.
|
|
8
|
+
*
|
|
9
|
+
* Mopro provides native witness calculation and proof generation through
|
|
10
|
+
* Rust FFI bindings, bypassing React Native's WebAssembly limitations.
|
|
11
|
+
*
|
|
12
|
+
* Performance Benefits:
|
|
13
|
+
* - Witness generation: 2-29x faster than browser SnarkJS
|
|
14
|
+
* - Proof generation: 8-15x faster than browser SnarkJS
|
|
15
|
+
* - Native iOS/Android performance
|
|
16
|
+
* - No network calls required
|
|
17
|
+
*
|
|
18
|
+
* @see https://zkmopro.org/docs/intro
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.createMoproProver = exports.ProofLib = exports.MoproProverAdapter = exports.isMoproAvailable = exports.initializeMopro = void 0;
|
|
45
|
+
const runtime_1 = require("../util/runtime");
|
|
46
|
+
/**
|
|
47
|
+
* Mopro ProofLib enum for selecting proof backend
|
|
48
|
+
*/
|
|
49
|
+
var ProofLib;
|
|
50
|
+
(function (ProofLib) {
|
|
51
|
+
ProofLib["Arkworks"] = "Arkworks";
|
|
52
|
+
ProofLib["Rapidsnark"] = "Rapidsnark";
|
|
53
|
+
})(ProofLib || (ProofLib = {}));
|
|
54
|
+
exports.ProofLib = ProofLib;
|
|
55
|
+
let moproModule = null;
|
|
56
|
+
/**
|
|
57
|
+
* Initialize Mopro module
|
|
58
|
+
* Dynamically imports mopro-ffi to avoid compilation errors when not installed
|
|
59
|
+
*/
|
|
60
|
+
const initializeMopro = async () => {
|
|
61
|
+
var _a;
|
|
62
|
+
if (!runtime_1.isReactNative) {
|
|
63
|
+
console.log('🖥️ Not in React Native environment, skipping mopro initialization');
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
console.log('📱 Initializing Mopro for React Native...');
|
|
68
|
+
// Dynamic import to avoid errors when mopro-ffi is not installed
|
|
69
|
+
let moproImport;
|
|
70
|
+
try {
|
|
71
|
+
const moduleName = 'mopro-ffi';
|
|
72
|
+
moproImport = await (_a = moduleName, Promise.resolve().then(() => __importStar(require(_a))));
|
|
73
|
+
}
|
|
74
|
+
catch (importError) {
|
|
75
|
+
console.log('📝 mopro-ffi not available:', String(importError));
|
|
76
|
+
console.log('💡 Install mopro-ffi for on-device proof generation:');
|
|
77
|
+
console.log(' npm install mopro-ffi');
|
|
78
|
+
console.log(' Follow setup guide: https://zkmopro.org/docs/setup/react-native-setup');
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
const { generateCircomProof, verifyCircomProof } = moproImport;
|
|
82
|
+
moproModule = {
|
|
83
|
+
generateCircomProof,
|
|
84
|
+
verifyCircomProof
|
|
85
|
+
};
|
|
86
|
+
console.log('✅ Mopro initialized successfully');
|
|
87
|
+
console.log('🚀 Fully on-device proof generation enabled');
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.warn('⚠️ Mopro initialization failed:', error);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
exports.initializeMopro = initializeMopro;
|
|
96
|
+
/**
|
|
97
|
+
* Check if Mopro is available and initialized
|
|
98
|
+
*/
|
|
99
|
+
const isMoproAvailable = () => {
|
|
100
|
+
return runtime_1.isReactNative && moproModule !== null;
|
|
101
|
+
};
|
|
102
|
+
exports.isMoproAvailable = isMoproAvailable;
|
|
103
|
+
/**
|
|
104
|
+
* Mopro Prover Adapter Class
|
|
105
|
+
*
|
|
106
|
+
* Provides a unified interface for generating proofs with Mopro
|
|
107
|
+
* that is compatible with DOP Engine's proof format.
|
|
108
|
+
*/
|
|
109
|
+
class MoproProverAdapter {
|
|
110
|
+
proofLib;
|
|
111
|
+
constructor(proofLib = ProofLib.Arkworks) {
|
|
112
|
+
this.proofLib = proofLib;
|
|
113
|
+
if (!(0, exports.isMoproAvailable)()) {
|
|
114
|
+
throw new Error('Mopro is not initialized. Call initializeMopro() first.');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate a zero-knowledge proof using Mopro
|
|
119
|
+
*
|
|
120
|
+
* @param circuitId - Circuit identifier for logging/debugging
|
|
121
|
+
* @param zkeyPath - Path to the zkey file on device filesystem
|
|
122
|
+
* @param jsonInputs - Circuit inputs in JSON format
|
|
123
|
+
* @param progressCallback - Optional progress callback (0-100)
|
|
124
|
+
* @returns DOP Engine compatible proof object
|
|
125
|
+
*/
|
|
126
|
+
async generateProof(circuitId, zkeyPath, jsonInputs, progressCallback) {
|
|
127
|
+
if (!moproModule) {
|
|
128
|
+
throw new Error('Mopro module not initialized');
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
console.log(`🔐 Generating proof with Mopro for circuit: ${circuitId}`);
|
|
132
|
+
const startTime = Date.now();
|
|
133
|
+
if (progressCallback) {
|
|
134
|
+
progressCallback(10);
|
|
135
|
+
}
|
|
136
|
+
// Convert circuit inputs to JSON string
|
|
137
|
+
const circuitInputsJson = JSON.stringify(jsonInputs);
|
|
138
|
+
// Remove 'file://' prefix if present
|
|
139
|
+
const cleanZkeyPath = zkeyPath.replace('file://', '');
|
|
140
|
+
if (progressCallback) {
|
|
141
|
+
progressCallback(20);
|
|
142
|
+
}
|
|
143
|
+
// Generate proof using Mopro
|
|
144
|
+
console.log(` Using proof backend: ${this.proofLib}`);
|
|
145
|
+
const moproResult = moproModule.generateCircomProof(cleanZkeyPath, circuitInputsJson, this.proofLib);
|
|
146
|
+
if (progressCallback) {
|
|
147
|
+
progressCallback(90);
|
|
148
|
+
}
|
|
149
|
+
// Convert Mopro proof format to DOP Engine format
|
|
150
|
+
const dopProof = MoproProverAdapter.convertMoproProofToDopFormat(moproResult);
|
|
151
|
+
const elapsedTime = Date.now() - startTime;
|
|
152
|
+
console.log(`✅ Proof generated successfully in ${elapsedTime}ms`);
|
|
153
|
+
if (progressCallback) {
|
|
154
|
+
progressCallback(100);
|
|
155
|
+
}
|
|
156
|
+
return dopProof;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
console.error(`❌ Mopro proof generation failed for ${circuitId}:`, error);
|
|
160
|
+
throw new Error(`Mopro proof generation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Verify a proof using Mopro (optional, for debugging)
|
|
165
|
+
*
|
|
166
|
+
* @param zkeyPath - Path to the zkey file
|
|
167
|
+
* @param proof - The proof to verify
|
|
168
|
+
* @returns true if proof is valid
|
|
169
|
+
*/
|
|
170
|
+
async verifyProof(zkeyPath, proof) {
|
|
171
|
+
if (!moproModule) {
|
|
172
|
+
throw new Error('Mopro module not initialized');
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const cleanZkeyPath = zkeyPath.replace('file://', '');
|
|
176
|
+
const isValid = moproModule.verifyCircomProof(cleanZkeyPath, proof, this.proofLib);
|
|
177
|
+
console.log(`🔍 Proof verification result: ${isValid ? '✅ Valid' : '❌ Invalid'}`);
|
|
178
|
+
return isValid;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
console.error('❌ Proof verification failed:', error);
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Convert Mopro proof format to DOP Engine format
|
|
187
|
+
*
|
|
188
|
+
* Mopro format:
|
|
189
|
+
* {
|
|
190
|
+
* proof: { a: [string, string], b: [[string, string], [string, string]], c: [string, string] },
|
|
191
|
+
* pub_signals: string[]
|
|
192
|
+
* }
|
|
193
|
+
*
|
|
194
|
+
* DOP Engine format:
|
|
195
|
+
* {
|
|
196
|
+
* pi_a: [string, string],
|
|
197
|
+
* pi_b: [[string, string], [string, string]],
|
|
198
|
+
* pi_c: [string, string]
|
|
199
|
+
* }
|
|
200
|
+
*
|
|
201
|
+
* Note: Public signals are handled separately by DOP Engine
|
|
202
|
+
*/
|
|
203
|
+
static convertMoproProofToDopFormat(moproResult) {
|
|
204
|
+
return {
|
|
205
|
+
pi_a: [moproResult.proof.a[0], moproResult.proof.a[1]],
|
|
206
|
+
pi_b: [
|
|
207
|
+
[moproResult.proof.b[0][0], moproResult.proof.b[0][1]],
|
|
208
|
+
[moproResult.proof.b[1][0], moproResult.proof.b[1][1]]
|
|
209
|
+
],
|
|
210
|
+
pi_c: [moproResult.proof.c[0], moproResult.proof.c[1]]
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get public signals from Mopro proof result
|
|
215
|
+
* DOP Engine may need these separately
|
|
216
|
+
*/
|
|
217
|
+
static getPublicSignals(moproResult) {
|
|
218
|
+
return moproResult.pub_signals;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Set the proof backend (Arkworks or Rapidsnark)
|
|
222
|
+
*
|
|
223
|
+
* Arkworks: Pure Rust implementation, consistent performance
|
|
224
|
+
* Rapidsnark: C++ optimized, potentially faster on some devices
|
|
225
|
+
*/
|
|
226
|
+
setProofLib(proofLib) {
|
|
227
|
+
this.proofLib = proofLib;
|
|
228
|
+
console.log(`📝 Mopro proof backend set to: ${proofLib}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.MoproProverAdapter = MoproProverAdapter;
|
|
232
|
+
/**
|
|
233
|
+
* Create a configured Mopro prover adapter
|
|
234
|
+
*
|
|
235
|
+
* @param useRapidsnark - Use Rapidsnark backend instead of Arkworks
|
|
236
|
+
* @returns Configured MoproProverAdapter instance
|
|
237
|
+
*/
|
|
238
|
+
const createMoproProver = (useRapidsnark = false) => {
|
|
239
|
+
const proofLib = useRapidsnark ? ProofLib.Rapidsnark : ProofLib.Arkworks;
|
|
240
|
+
return new MoproProverAdapter(proofLib);
|
|
241
|
+
};
|
|
242
|
+
exports.createMoproProver = createMoproProver;
|
|
243
|
+
//# sourceMappingURL=mopro-prover-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mopro-prover-adapter.js","sourceRoot":"","sources":["../../../../src/services/dop/crypto/mopro-prover-adapter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mopro Prover Adapter for React Native\n * \n * This adapter enables fully on-device zero-knowledge proof generation\n * using the Mopro (Mobile Prover) toolkit, eliminating the need for\n * backend witness generation services.\n * \n * Mopro provides native witness calculation and proof generation through\n * Rust FFI bindings, bypassing React Native's WebAssembly limitations.\n * \n * Performance Benefits:\n * - Witness generation: 2-29x faster than browser SnarkJS\n * - Proof generation: 8-15x faster than browser SnarkJS\n * - Native iOS/Android performance\n * - No network calls required\n * \n * @see https://zkmopro.org/docs/intro\n */\n\nimport { isReactNative } from '../util/runtime';\nimport type { FormattedCircuitInputsDop, Proof } from 'dop-engine-v3';\n\n/**\n * Mopro CircomProofResult structure\n * This is the proof format returned by mopro's generateCircomProof\n */\ninterface MoproCircomProofResult {\n proof: {\n a: string[];\n b: string[][];\n c: string[];\n };\n pub_signals: string[];\n}\n\n/**\n * Mopro ProofLib enum for selecting proof backend\n */\nenum ProofLib {\n Arkworks = 'Arkworks',\n Rapidsnark = 'Rapidsnark'\n}\n\n/**\n * Mopro FFI interface (dynamically imported)\n */\ninterface MoproFFI {\n generateCircomProof: (\n zkeyPath: string,\n circuitInputsJson: string,\n proofLib: ProofLib\n ) => MoproCircomProofResult;\n \n verifyCircomProof: (\n zkeyPath: string,\n proof: MoproCircomProofResult,\n proofLib: ProofLib\n ) => boolean;\n}\n\nlet moproModule: MoproFFI | null = null;\n\n/**\n * Initialize Mopro module\n * Dynamically imports mopro-ffi to avoid compilation errors when not installed\n */\nexport const initializeMopro = async (): Promise<boolean> => {\n if (!isReactNative) {\n console.log('🖥️ Not in React Native environment, skipping mopro initialization');\n return false;\n }\n\n try {\n console.log('📱 Initializing Mopro for React Native...');\n \n // Dynamic import to avoid errors when mopro-ffi is not installed\n let moproImport: unknown;\n try {\n const moduleName = 'mopro-ffi';\n moproImport = await import(moduleName);\n } catch (importError) {\n console.log('📝 mopro-ffi not available:', String(importError));\n console.log('💡 Install mopro-ffi for on-device proof generation:');\n console.log(' npm install mopro-ffi');\n console.log(' Follow setup guide: https://zkmopro.org/docs/setup/react-native-setup');\n return false;\n }\n \n const { generateCircomProof, verifyCircomProof } = moproImport as {\n generateCircomProof: MoproFFI['generateCircomProof'];\n verifyCircomProof: MoproFFI['verifyCircomProof'];\n };\n \n moproModule = {\n generateCircomProof,\n verifyCircomProof\n };\n \n console.log('✅ Mopro initialized successfully');\n console.log('🚀 Fully on-device proof generation enabled');\n return true;\n \n } catch (error) {\n console.warn('⚠️ Mopro initialization failed:', error);\n return false;\n }\n};\n\n/**\n * Check if Mopro is available and initialized\n */\nexport const isMoproAvailable = (): boolean => {\n return isReactNative && moproModule !== null;\n};\n\n/**\n * Mopro Prover Adapter Class\n * \n * Provides a unified interface for generating proofs with Mopro\n * that is compatible with DOP Engine's proof format.\n */\nexport class MoproProverAdapter {\n private proofLib: ProofLib;\n\n constructor(proofLib: ProofLib = ProofLib.Arkworks) {\n this.proofLib = proofLib;\n \n if (!isMoproAvailable()) {\n throw new Error(\n 'Mopro is not initialized. Call initializeMopro() first.'\n );\n }\n }\n\n /**\n * Generate a zero-knowledge proof using Mopro\n * \n * @param circuitId - Circuit identifier for logging/debugging\n * @param zkeyPath - Path to the zkey file on device filesystem\n * @param jsonInputs - Circuit inputs in JSON format\n * @param progressCallback - Optional progress callback (0-100)\n * @returns DOP Engine compatible proof object\n */\n async generateProof(\n circuitId: string,\n zkeyPath: string,\n jsonInputs: FormattedCircuitInputsDop,\n progressCallback?: (progress: number) => void\n ): Promise<Proof> {\n if (!moproModule) {\n throw new Error('Mopro module not initialized');\n }\n\n try {\n console.log(`🔐 Generating proof with Mopro for circuit: ${circuitId}`);\n const startTime = Date.now();\n\n if (progressCallback) {\n progressCallback(10);\n }\n\n // Convert circuit inputs to JSON string\n const circuitInputsJson = JSON.stringify(jsonInputs);\n \n // Remove 'file://' prefix if present\n const cleanZkeyPath = zkeyPath.replace('file://', '');\n\n if (progressCallback) {\n progressCallback(20);\n }\n\n // Generate proof using Mopro\n console.log(` Using proof backend: ${this.proofLib}`);\n const moproResult: MoproCircomProofResult = moproModule.generateCircomProof(\n cleanZkeyPath,\n circuitInputsJson,\n this.proofLib\n );\n\n if (progressCallback) {\n progressCallback(90);\n }\n\n // Convert Mopro proof format to DOP Engine format\n const dopProof: Proof = MoproProverAdapter.convertMoproProofToDopFormat(moproResult);\n\n const elapsedTime = Date.now() - startTime;\n console.log(`✅ Proof generated successfully in ${elapsedTime}ms`);\n\n if (progressCallback) {\n progressCallback(100);\n }\n\n return dopProof;\n\n } catch (error) {\n console.error(`❌ Mopro proof generation failed for ${circuitId}:`, error);\n throw new Error(\n `Mopro proof generation failed: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n /**\n * Verify a proof using Mopro (optional, for debugging)\n * \n * @param zkeyPath - Path to the zkey file\n * @param proof - The proof to verify\n * @returns true if proof is valid\n */\n async verifyProof(\n zkeyPath: string,\n proof: MoproCircomProofResult\n ): Promise<boolean> {\n if (!moproModule) {\n throw new Error('Mopro module not initialized');\n }\n\n try {\n const cleanZkeyPath = zkeyPath.replace('file://', '');\n const isValid = moproModule.verifyCircomProof(\n cleanZkeyPath,\n proof,\n this.proofLib\n );\n \n console.log(`🔍 Proof verification result: ${isValid ? '✅ Valid' : '❌ Invalid'}`);\n return isValid;\n\n } catch (error) {\n console.error('❌ Proof verification failed:', error);\n return false;\n }\n }\n\n /**\n * Convert Mopro proof format to DOP Engine format\n * \n * Mopro format:\n * {\n * proof: { a: [string, string], b: [[string, string], [string, string]], c: [string, string] },\n * pub_signals: string[]\n * }\n * \n * DOP Engine format:\n * {\n * pi_a: [string, string],\n * pi_b: [[string, string], [string, string]],\n * pi_c: [string, string]\n * }\n * \n * Note: Public signals are handled separately by DOP Engine\n */\n private static convertMoproProofToDopFormat(moproResult: MoproCircomProofResult): Proof {\n return {\n pi_a: [moproResult.proof.a[0], moproResult.proof.a[1]],\n pi_b: [\n [moproResult.proof.b[0][0], moproResult.proof.b[0][1]],\n [moproResult.proof.b[1][0], moproResult.proof.b[1][1]]\n ],\n pi_c: [moproResult.proof.c[0], moproResult.proof.c[1]]\n };\n }\n\n /**\n * Get public signals from Mopro proof result\n * DOP Engine may need these separately\n */\n static getPublicSignals(moproResult: MoproCircomProofResult): string[] {\n return moproResult.pub_signals;\n }\n\n /**\n * Set the proof backend (Arkworks or Rapidsnark)\n * \n * Arkworks: Pure Rust implementation, consistent performance\n * Rapidsnark: C++ optimized, potentially faster on some devices\n */\n setProofLib(proofLib: ProofLib): void {\n this.proofLib = proofLib;\n console.log(`📝 Mopro proof backend set to: ${proofLib}`);\n }\n}\n\n/**\n * Export ProofLib enum for external use\n */\nexport { ProofLib };\n\n/**\n * Create a configured Mopro prover adapter\n * \n * @param useRapidsnark - Use Rapidsnark backend instead of Arkworks\n * @returns Configured MoproProverAdapter instance\n */\nexport const createMoproProver = (useRapidsnark = false): MoproProverAdapter => {\n const proofLib = useRapidsnark ? ProofLib.Rapidsnark : ProofLib.Arkworks;\n return new MoproProverAdapter(proofLib);\n};\n"]}
|
package/package.json
CHANGED
package/react-native.js
CHANGED
|
@@ -14,4 +14,11 @@ const sdk = require('./dist/index.js');
|
|
|
14
14
|
// Export React Native-specific prover utilities
|
|
15
15
|
sdk.reactNativeRapidsnark = require('./dist/services/dop/crypto/react-native-rapidsnark-prover.js');
|
|
16
16
|
|
|
17
|
+
// Export Mopro integration
|
|
18
|
+
sdk.mopro = {
|
|
19
|
+
...require('./dist/services/dop/crypto/mopro-prover-adapter.js'),
|
|
20
|
+
...require('./dist/services/dop/crypto/mopro-circuit-loader.js'),
|
|
21
|
+
...require('./dist/services/dop/core/react-native-prover-setup.js')
|
|
22
|
+
};
|
|
23
|
+
|
|
17
24
|
module.exports = sdk;
|