@cofhe/sdk 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/adapters/ethers6.ts +28 -28
- package/adapters/hardhat.ts +0 -1
- package/adapters/index.test.ts +14 -19
- package/adapters/smartWallet.ts +81 -73
- package/adapters/test-utils.ts +45 -45
- package/adapters/types.ts +3 -3
- package/chains/chains/localcofhe.ts +14 -0
- package/chains/chains.test.ts +2 -1
- package/chains/index.ts +3 -1
- package/core/baseBuilder.ts +30 -49
- package/core/client.test.ts +94 -77
- package/core/client.ts +133 -149
- package/core/clientTypes.ts +108 -0
- package/core/config.test.ts +22 -11
- package/core/config.ts +16 -9
- package/core/decrypt/decryptHandleBuilder.ts +51 -45
- package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
- package/core/decrypt/tnSealOutputV2.ts +298 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +16 -10
- package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
- package/core/encrypt/encryptInputsBuilder.ts +159 -111
- package/core/encrypt/encryptUtils.ts +6 -3
- package/core/encrypt/zkPackProveVerify.ts +70 -8
- package/core/error.ts +0 -2
- package/core/fetchKeys.test.ts +1 -18
- package/core/fetchKeys.ts +0 -26
- package/core/index.ts +29 -17
- package/core/keyStore.ts +65 -38
- package/core/permits.test.ts +253 -1
- package/core/permits.ts +80 -16
- package/core/types.ts +198 -152
- package/core/utils.ts +43 -1
- package/dist/adapters.d.cts +38 -20
- package/dist/adapters.d.ts +38 -20
- package/dist/chains.cjs +14 -1
- package/dist/chains.d.cts +23 -1
- package/dist/chains.d.ts +23 -1
- package/dist/chains.js +1 -1
- package/dist/{chunk-LU7BMUUT.js → chunk-UGBVZNRT.js} +39 -25
- package/dist/{chunk-GZCQQYVI.js → chunk-WEAZ25JO.js} +14 -2
- package/dist/{chunk-KFGPTJ6X.js → chunk-WGCRJCBR.js} +1920 -1692
- package/dist/{types-bB7wLj0q.d.cts → clientTypes-5_1nwtUe.d.cts} +308 -347
- package/dist/{types-PhwGgQvs.d.ts → clientTypes-Es7fyi65.d.ts} +308 -347
- package/dist/core.cjs +2872 -2632
- package/dist/core.d.cts +101 -6
- package/dist/core.d.ts +101 -6
- package/dist/core.js +3 -3
- package/dist/node.cjs +2716 -2520
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +4 -3
- package/dist/{permit-S9CnI6MF.d.cts → permit-fUSe6KKq.d.cts} +31 -15
- package/dist/{permit-S9CnI6MF.d.ts → permit-fUSe6KKq.d.ts} +31 -15
- package/dist/permits.cjs +39 -24
- package/dist/permits.d.cts +137 -148
- package/dist/permits.d.ts +137 -148
- package/dist/permits.js +1 -1
- package/dist/web.cjs +2929 -2518
- package/dist/web.d.cts +21 -5
- package/dist/web.d.ts +21 -5
- package/dist/web.js +185 -9
- package/dist/zkProve.worker.cjs +93 -0
- package/dist/zkProve.worker.d.cts +2 -0
- package/dist/zkProve.worker.d.ts +2 -0
- package/dist/zkProve.worker.js +91 -0
- package/node/client.test.ts +20 -25
- package/node/encryptInputs.test.ts +18 -38
- package/node/index.ts +1 -0
- package/package.json +14 -14
- package/permits/index.ts +1 -0
- package/permits/localstorage.test.ts +0 -1
- package/permits/permit.test.ts +25 -22
- package/permits/permit.ts +30 -21
- package/permits/sealing.test.ts +3 -3
- package/permits/sealing.ts +2 -2
- package/permits/store.ts +5 -7
- package/permits/test-utils.ts +1 -1
- package/permits/types.ts +17 -0
- package/permits/utils.ts +0 -1
- package/permits/validation.ts +24 -4
- package/web/client.web.test.ts +20 -25
- package/web/config.web.test.ts +0 -2
- package/web/encryptInputs.web.test.ts +31 -54
- package/web/index.ts +65 -1
- package/web/storage.ts +19 -5
- package/web/worker.builder.web.test.ts +148 -0
- package/web/worker.config.web.test.ts +329 -0
- package/web/worker.output.web.test.ts +84 -0
- package/web/workerManager.test.ts +80 -0
- package/web/workerManager.ts +214 -0
- package/web/workerManager.web.test.ts +114 -0
- package/web/zkProve.worker.ts +133 -0
- package/core/result.test.ts +0 -180
- package/core/result.ts +0 -67
- package/core/test-utils.ts +0 -45
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { hardhat } from './chunk-
|
|
2
|
-
import { permitStore, PermitUtils } from './chunk-
|
|
1
|
+
import { hardhat as hardhat$1 } from './chunk-WEAZ25JO.js';
|
|
2
|
+
import { permitStore, PermitUtils } from './chunk-UGBVZNRT.js';
|
|
3
3
|
import { createStore } from 'zustand/vanilla';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { hardhat as hardhat$1 } from 'viem/chains';
|
|
4
|
+
import { createWalletClient, http, encodePacked, keccak256, toBytes, hashMessage, getAddress } from 'viem';
|
|
5
|
+
import { hardhat } from 'viem/chains';
|
|
7
6
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
7
|
+
import { z } from 'zod';
|
|
8
8
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
9
9
|
import { produce } from 'immer';
|
|
10
10
|
|
|
@@ -143,250 +143,123 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
143
143
|
};
|
|
144
144
|
var isCofhesdkError = (error) => error instanceof CofhesdkError;
|
|
145
145
|
|
|
146
|
-
// core/
|
|
147
|
-
var
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const permit = await permitMethod(options, publicClient, walletClient);
|
|
204
|
-
await storeActivePermit(permit, publicClient, walletClient);
|
|
205
|
-
return permit;
|
|
206
|
-
};
|
|
207
|
-
var createSelf = async (options, publicClient, walletClient) => {
|
|
208
|
-
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
|
|
209
|
-
};
|
|
210
|
-
var createSharing = async (options, publicClient, walletClient) => {
|
|
211
|
-
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
|
|
212
|
-
};
|
|
213
|
-
var importShared = async (options, publicClient, walletClient) => {
|
|
214
|
-
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
|
|
215
|
-
};
|
|
216
|
-
var getHash = (permit) => {
|
|
217
|
-
return PermitUtils.getHash(permit);
|
|
218
|
-
};
|
|
219
|
-
var serialize = (permit) => {
|
|
220
|
-
return PermitUtils.serialize(permit);
|
|
221
|
-
};
|
|
222
|
-
var deserialize = (serialized) => {
|
|
223
|
-
return PermitUtils.deserialize(serialized);
|
|
224
|
-
};
|
|
225
|
-
var getPermit = async (chainId, account, hash) => {
|
|
226
|
-
return permitStore.getPermit(chainId, account, hash);
|
|
227
|
-
};
|
|
228
|
-
var getPermits = async (chainId, account) => {
|
|
229
|
-
return permitStore.getPermits(chainId, account);
|
|
230
|
-
};
|
|
231
|
-
var getActivePermit = async (chainId, account) => {
|
|
232
|
-
return permitStore.getActivePermit(chainId, account);
|
|
233
|
-
};
|
|
234
|
-
var getActivePermitHash = async (chainId, account) => {
|
|
235
|
-
return permitStore.getActivePermitHash(chainId, account);
|
|
236
|
-
};
|
|
237
|
-
var selectActivePermit = async (chainId, account, hash) => {
|
|
238
|
-
await permitStore.setActivePermitHash(chainId, account, hash);
|
|
239
|
-
};
|
|
240
|
-
var removePermit = async (chainId, account, hash) => {
|
|
241
|
-
await permitStore.removePermit(chainId, account, hash);
|
|
242
|
-
};
|
|
243
|
-
var removeActivePermit = async (chainId, account) => {
|
|
244
|
-
await permitStore.removeActivePermitHash(chainId, account);
|
|
245
|
-
};
|
|
246
|
-
var permits = {
|
|
247
|
-
getSnapshot: permitStore.store.getState,
|
|
248
|
-
subscribe: permitStore.store.subscribe,
|
|
249
|
-
createSelf,
|
|
250
|
-
createSharing,
|
|
251
|
-
importShared,
|
|
252
|
-
getHash,
|
|
253
|
-
serialize,
|
|
254
|
-
deserialize,
|
|
255
|
-
getPermit,
|
|
256
|
-
getPermits,
|
|
257
|
-
getActivePermit,
|
|
258
|
-
getActivePermitHash,
|
|
259
|
-
removePermit,
|
|
260
|
-
selectActivePermit,
|
|
261
|
-
removeActivePermit
|
|
262
|
-
};
|
|
263
|
-
function uint160ToAddress(uint160) {
|
|
264
|
-
const hexStr = uint160.toString(16).padStart(40, "0");
|
|
265
|
-
return getAddress("0x" + hexStr);
|
|
146
|
+
// core/types.ts
|
|
147
|
+
var FheTypes = /* @__PURE__ */ ((FheTypes2) => {
|
|
148
|
+
FheTypes2[FheTypes2["Bool"] = 0] = "Bool";
|
|
149
|
+
FheTypes2[FheTypes2["Uint4"] = 1] = "Uint4";
|
|
150
|
+
FheTypes2[FheTypes2["Uint8"] = 2] = "Uint8";
|
|
151
|
+
FheTypes2[FheTypes2["Uint16"] = 3] = "Uint16";
|
|
152
|
+
FheTypes2[FheTypes2["Uint32"] = 4] = "Uint32";
|
|
153
|
+
FheTypes2[FheTypes2["Uint64"] = 5] = "Uint64";
|
|
154
|
+
FheTypes2[FheTypes2["Uint128"] = 6] = "Uint128";
|
|
155
|
+
FheTypes2[FheTypes2["Uint160"] = 7] = "Uint160";
|
|
156
|
+
FheTypes2[FheTypes2["Uint256"] = 8] = "Uint256";
|
|
157
|
+
FheTypes2[FheTypes2["Uint512"] = 9] = "Uint512";
|
|
158
|
+
FheTypes2[FheTypes2["Uint1024"] = 10] = "Uint1024";
|
|
159
|
+
FheTypes2[FheTypes2["Uint2048"] = 11] = "Uint2048";
|
|
160
|
+
FheTypes2[FheTypes2["Uint2"] = 12] = "Uint2";
|
|
161
|
+
FheTypes2[FheTypes2["Uint6"] = 13] = "Uint6";
|
|
162
|
+
FheTypes2[FheTypes2["Uint10"] = 14] = "Uint10";
|
|
163
|
+
FheTypes2[FheTypes2["Uint12"] = 15] = "Uint12";
|
|
164
|
+
FheTypes2[FheTypes2["Uint14"] = 16] = "Uint14";
|
|
165
|
+
FheTypes2[FheTypes2["Int2"] = 17] = "Int2";
|
|
166
|
+
FheTypes2[FheTypes2["Int4"] = 18] = "Int4";
|
|
167
|
+
FheTypes2[FheTypes2["Int6"] = 19] = "Int6";
|
|
168
|
+
FheTypes2[FheTypes2["Int8"] = 20] = "Int8";
|
|
169
|
+
FheTypes2[FheTypes2["Int10"] = 21] = "Int10";
|
|
170
|
+
FheTypes2[FheTypes2["Int12"] = 22] = "Int12";
|
|
171
|
+
FheTypes2[FheTypes2["Int14"] = 23] = "Int14";
|
|
172
|
+
FheTypes2[FheTypes2["Int16"] = 24] = "Int16";
|
|
173
|
+
FheTypes2[FheTypes2["Int32"] = 25] = "Int32";
|
|
174
|
+
FheTypes2[FheTypes2["Int64"] = 26] = "Int64";
|
|
175
|
+
FheTypes2[FheTypes2["Int128"] = 27] = "Int128";
|
|
176
|
+
FheTypes2[FheTypes2["Int160"] = 28] = "Int160";
|
|
177
|
+
FheTypes2[FheTypes2["Int256"] = 29] = "Int256";
|
|
178
|
+
return FheTypes2;
|
|
179
|
+
})(FheTypes || {});
|
|
180
|
+
var FheUintUTypes = [
|
|
181
|
+
2 /* Uint8 */,
|
|
182
|
+
3 /* Uint16 */,
|
|
183
|
+
4 /* Uint32 */,
|
|
184
|
+
5 /* Uint64 */,
|
|
185
|
+
6 /* Uint128 */
|
|
186
|
+
// [U256-DISABLED]
|
|
187
|
+
// FheTypes.Uint256,
|
|
188
|
+
];
|
|
189
|
+
var FheAllUTypes = [
|
|
190
|
+
0 /* Bool */,
|
|
191
|
+
2 /* Uint8 */,
|
|
192
|
+
3 /* Uint16 */,
|
|
193
|
+
4 /* Uint32 */,
|
|
194
|
+
5 /* Uint64 */,
|
|
195
|
+
6 /* Uint128 */,
|
|
196
|
+
// [U256-DISABLED]
|
|
197
|
+
// FheTypes.Uint256,
|
|
198
|
+
7 /* Uint160 */
|
|
199
|
+
];
|
|
200
|
+
function assertCorrectEncryptedItemInput(input) {
|
|
201
|
+
if (!input.signature.startsWith("0x"))
|
|
202
|
+
throw new Error("Signature must be a hex string starting with 0x");
|
|
266
203
|
}
|
|
267
|
-
var
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
|
|
279
|
-
}
|
|
204
|
+
var EncryptableFactoriesImpl = {
|
|
205
|
+
bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
|
|
206
|
+
address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
|
|
207
|
+
uint8: (data, securityZone = 0) => ({ data, securityZone, utype: 2 /* Uint8 */ }),
|
|
208
|
+
uint16: (data, securityZone = 0) => ({ data, securityZone, utype: 3 /* Uint16 */ }),
|
|
209
|
+
uint32: (data, securityZone = 0) => ({ data, securityZone, utype: 4 /* Uint32 */ }),
|
|
210
|
+
uint64: (data, securityZone = 0) => ({ data, securityZone, utype: 5 /* Uint64 */ }),
|
|
211
|
+
uint128: (data, securityZone = 0) => ({ data, securityZone, utype: 6 /* Uint128 */ })
|
|
212
|
+
// [U256-DISABLED]
|
|
213
|
+
// uint256: (data: EncryptableUint256['data'], securityZone = 0) =>
|
|
214
|
+
// ({ data, securityZone, utype: FheTypes.Uint256 }) as EncryptableUint256,
|
|
280
215
|
};
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (this.chainId)
|
|
303
|
-
return this.chainId;
|
|
304
|
-
throw new CofhesdkError({
|
|
305
|
-
code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
|
|
306
|
-
message: "Chain ID is not set",
|
|
307
|
-
hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
|
|
308
|
-
context: {
|
|
309
|
-
chainId: this.chainId
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Gets the account address from the instance or fetches it from the wallet client
|
|
315
|
-
* @returns The account address
|
|
316
|
-
* @throws {CofhesdkError} If account is not set and walletClient is not available
|
|
317
|
-
*/
|
|
318
|
-
async getAccountOrThrow() {
|
|
319
|
-
if (this.account)
|
|
320
|
-
return this.account;
|
|
321
|
-
throw new CofhesdkError({
|
|
322
|
-
code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
|
|
323
|
-
message: "Account is not set",
|
|
324
|
-
hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
|
|
325
|
-
context: {
|
|
326
|
-
account: this.account
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Gets the config or throws an error if not available
|
|
332
|
-
* @returns The config
|
|
333
|
-
* @throws {CofhesdkError} If config is not set
|
|
334
|
-
*/
|
|
335
|
-
getConfigOrThrow() {
|
|
336
|
-
if (this.config)
|
|
337
|
-
return this.config;
|
|
338
|
-
throw new CofhesdkError({
|
|
339
|
-
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
340
|
-
message: "Builder config is undefined",
|
|
341
|
-
hint: "Ensure client has been created with a config.",
|
|
342
|
-
context: {
|
|
343
|
-
config: this.config
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Gets the public client or throws an error if not available
|
|
349
|
-
* @returns The public client
|
|
350
|
-
* @throws {CofhesdkError} If publicClient is not set
|
|
351
|
-
*/
|
|
352
|
-
getPublicClientOrThrow() {
|
|
353
|
-
if (this.publicClient)
|
|
354
|
-
return this.publicClient;
|
|
355
|
-
throw new CofhesdkError({
|
|
356
|
-
code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
|
|
357
|
-
message: "Public client not found",
|
|
358
|
-
hint: "Ensure client.connect() has been called with a publicClient.",
|
|
359
|
-
context: {
|
|
360
|
-
publicClient: this.publicClient
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Gets the wallet client or throws an error if not available
|
|
366
|
-
* @returns The wallet client
|
|
367
|
-
* @throws {CofhesdkError} If walletClient is not set
|
|
368
|
-
*/
|
|
369
|
-
getWalletClientOrThrow() {
|
|
370
|
-
if (this.walletClient)
|
|
371
|
-
return this.walletClient;
|
|
372
|
-
throw new CofhesdkError({
|
|
373
|
-
code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
|
|
374
|
-
message: "Wallet client not found",
|
|
375
|
-
hint: "Ensure client.connect() has been called with a walletClient.",
|
|
376
|
-
context: {
|
|
377
|
-
walletClient: this.walletClient
|
|
378
|
-
}
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
/**
|
|
382
|
-
* Requires the client to be connected
|
|
383
|
-
* @throws {CofhesdkError} If client is not connected
|
|
384
|
-
*/
|
|
385
|
-
requireConnectedOrThrow() {
|
|
386
|
-
if (this.requireConnected)
|
|
387
|
-
this.requireConnected();
|
|
216
|
+
function createEncryptableByLiteral(type, data, securityZone = 0) {
|
|
217
|
+
switch (type) {
|
|
218
|
+
case "bool": {
|
|
219
|
+
if (typeof data !== "boolean")
|
|
220
|
+
throw new Error("Bool encryptable data must be boolean");
|
|
221
|
+
return EncryptableFactoriesImpl.bool(data, securityZone);
|
|
222
|
+
}
|
|
223
|
+
case "address":
|
|
224
|
+
case "uint8":
|
|
225
|
+
case "uint16":
|
|
226
|
+
case "uint32":
|
|
227
|
+
case "uint64":
|
|
228
|
+
case "uint128": {
|
|
229
|
+
if (typeof data === "boolean")
|
|
230
|
+
throw new Error("Uint encryptable data must be string or bigint");
|
|
231
|
+
return EncryptableFactoriesImpl[type](data, securityZone);
|
|
232
|
+
}
|
|
233
|
+
default: {
|
|
234
|
+
const _exhaustive = type;
|
|
235
|
+
throw new Error(`Unsupported encryptable type: ${_exhaustive}`);
|
|
236
|
+
}
|
|
388
237
|
}
|
|
238
|
+
}
|
|
239
|
+
var Encryptable = {
|
|
240
|
+
...EncryptableFactoriesImpl,
|
|
241
|
+
create: createEncryptableByLiteral
|
|
389
242
|
};
|
|
243
|
+
function isEncryptableItem(value) {
|
|
244
|
+
return (
|
|
245
|
+
// Is object and exists
|
|
246
|
+
typeof value === "object" && value !== null && // Has securityZone
|
|
247
|
+
"securityZone" in value && typeof value.securityZone === "number" && // Has utype
|
|
248
|
+
"utype" in value && FheAllUTypes.includes(value.utype) && // Has data
|
|
249
|
+
"data" in value && ["string", "number", "bigint", "boolean"].includes(typeof value.data)
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
var EncryptStep = /* @__PURE__ */ ((EncryptStep2) => {
|
|
253
|
+
EncryptStep2["InitTfhe"] = "initTfhe";
|
|
254
|
+
EncryptStep2["FetchKeys"] = "fetchKeys";
|
|
255
|
+
EncryptStep2["Pack"] = "pack";
|
|
256
|
+
EncryptStep2["Prove"] = "prove";
|
|
257
|
+
EncryptStep2["Verify"] = "verify";
|
|
258
|
+
return EncryptStep2;
|
|
259
|
+
})(EncryptStep || {});
|
|
260
|
+
function isLastEncryptionStep(step) {
|
|
261
|
+
return step === "verify" /* Verify */;
|
|
262
|
+
}
|
|
390
263
|
var toHexString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
|
391
264
|
var toBigIntOrThrow = (value) => {
|
|
392
265
|
if (typeof value === "bigint") {
|
|
@@ -455,969 +328,881 @@ async function getWalletClientAccount(walletClient) {
|
|
|
455
328
|
}
|
|
456
329
|
return address;
|
|
457
330
|
}
|
|
331
|
+
function fheTypeToString(utype) {
|
|
332
|
+
switch (utype) {
|
|
333
|
+
case 0 /* Bool */:
|
|
334
|
+
return "bool";
|
|
335
|
+
case 1 /* Uint4 */:
|
|
336
|
+
return "uint4";
|
|
337
|
+
case 2 /* Uint8 */:
|
|
338
|
+
return "uint8";
|
|
339
|
+
case 3 /* Uint16 */:
|
|
340
|
+
return "uint16";
|
|
341
|
+
case 4 /* Uint32 */:
|
|
342
|
+
return "uint32";
|
|
343
|
+
case 5 /* Uint64 */:
|
|
344
|
+
return "uint64";
|
|
345
|
+
case 6 /* Uint128 */:
|
|
346
|
+
return "uint128";
|
|
347
|
+
case 7 /* Uint160 */:
|
|
348
|
+
return "uint160";
|
|
349
|
+
case 8 /* Uint256 */:
|
|
350
|
+
return "uint256";
|
|
351
|
+
case 9 /* Uint512 */:
|
|
352
|
+
return "uint512";
|
|
353
|
+
case 10 /* Uint1024 */:
|
|
354
|
+
return "uint1024";
|
|
355
|
+
case 11 /* Uint2048 */:
|
|
356
|
+
return "uint2048";
|
|
357
|
+
case 12 /* Uint2 */:
|
|
358
|
+
return "uint2";
|
|
359
|
+
case 13 /* Uint6 */:
|
|
360
|
+
return "uint6";
|
|
361
|
+
case 14 /* Uint10 */:
|
|
362
|
+
return "uint10";
|
|
363
|
+
default:
|
|
364
|
+
throw new Error(`Unknown FheType: ${utype}`);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
458
367
|
|
|
459
|
-
// core/
|
|
460
|
-
var
|
|
368
|
+
// core/encrypt/zkPackProveVerify.ts
|
|
369
|
+
var MAX_UINT8 = 255n;
|
|
370
|
+
var MAX_UINT16 = 65535n;
|
|
371
|
+
var MAX_UINT32 = 4294967295n;
|
|
372
|
+
var MAX_UINT64 = 18446744073709551615n;
|
|
373
|
+
var MAX_UINT128 = 340282366920938463463374607431768211455n;
|
|
374
|
+
var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
|
|
375
|
+
var MAX_ENCRYPTABLE_BITS = 2048;
|
|
376
|
+
var zkPack = (items, builder) => {
|
|
377
|
+
let totalBits = 0;
|
|
378
|
+
for (const item of items) {
|
|
379
|
+
switch (item.utype) {
|
|
380
|
+
case 0 /* Bool */: {
|
|
381
|
+
builder.push_boolean(item.data);
|
|
382
|
+
totalBits += 1;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
case 2 /* Uint8 */: {
|
|
386
|
+
const bint = toBigIntOrThrow(item.data);
|
|
387
|
+
validateBigIntInRange(bint, MAX_UINT8);
|
|
388
|
+
builder.push_u8(parseInt(bint.toString()));
|
|
389
|
+
totalBits += 8;
|
|
390
|
+
break;
|
|
391
|
+
}
|
|
392
|
+
case 3 /* Uint16 */: {
|
|
393
|
+
const bint = toBigIntOrThrow(item.data);
|
|
394
|
+
validateBigIntInRange(bint, MAX_UINT16);
|
|
395
|
+
builder.push_u16(parseInt(bint.toString()));
|
|
396
|
+
totalBits += 16;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
case 4 /* Uint32 */: {
|
|
400
|
+
const bint = toBigIntOrThrow(item.data);
|
|
401
|
+
validateBigIntInRange(bint, MAX_UINT32);
|
|
402
|
+
builder.push_u32(parseInt(bint.toString()));
|
|
403
|
+
totalBits += 32;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
case 5 /* Uint64 */: {
|
|
407
|
+
const bint = toBigIntOrThrow(item.data);
|
|
408
|
+
validateBigIntInRange(bint, MAX_UINT64);
|
|
409
|
+
builder.push_u64(bint);
|
|
410
|
+
totalBits += 64;
|
|
411
|
+
break;
|
|
412
|
+
}
|
|
413
|
+
case 6 /* Uint128 */: {
|
|
414
|
+
const bint = toBigIntOrThrow(item.data);
|
|
415
|
+
validateBigIntInRange(bint, MAX_UINT128);
|
|
416
|
+
builder.push_u128(bint);
|
|
417
|
+
totalBits += 128;
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
case 7 /* Uint160 */: {
|
|
421
|
+
const bint = toBigIntOrThrow(item.data);
|
|
422
|
+
validateBigIntInRange(bint, MAX_UINT160);
|
|
423
|
+
builder.push_u160(bint);
|
|
424
|
+
totalBits += 160;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
default: {
|
|
428
|
+
throw new CofhesdkError({
|
|
429
|
+
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
430
|
+
message: `Invalid utype: ${item.utype}`,
|
|
431
|
+
hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
|
|
432
|
+
context: {
|
|
433
|
+
item
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
440
|
+
throw new CofhesdkError({
|
|
441
|
+
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
442
|
+
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
443
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
444
|
+
context: {
|
|
445
|
+
totalBits,
|
|
446
|
+
maxBits: MAX_ENCRYPTABLE_BITS,
|
|
447
|
+
items
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
return builder;
|
|
452
|
+
};
|
|
453
|
+
var zkProveWithWorker = async (workerFn, fheKeyHex, crsHex, items, metadata) => {
|
|
454
|
+
return await workerFn(fheKeyHex, crsHex, items, metadata);
|
|
455
|
+
};
|
|
456
|
+
var zkProve = async (builder, crs, metadata) => {
|
|
457
|
+
return new Promise((resolve) => {
|
|
458
|
+
setTimeout(() => {
|
|
459
|
+
const compactList = builder.build_with_proof_packed(
|
|
460
|
+
crs,
|
|
461
|
+
metadata,
|
|
462
|
+
1
|
|
463
|
+
// ZkComputeLoad.Verify
|
|
464
|
+
);
|
|
465
|
+
resolve(compactList.serialize());
|
|
466
|
+
}, 0);
|
|
467
|
+
});
|
|
468
|
+
};
|
|
469
|
+
var constructZkPoKMetadata = (accountAddr, securityZone, chainId) => {
|
|
470
|
+
const accountAddrNoPrefix = accountAddr.startsWith("0x") ? accountAddr.slice(2) : accountAddr;
|
|
471
|
+
const accountBytes = hexToBytes(accountAddrNoPrefix);
|
|
472
|
+
const chainIdBytes = new Uint8Array(32);
|
|
473
|
+
let value = chainId;
|
|
474
|
+
for (let i = 31; i >= 0 && value > 0; i--) {
|
|
475
|
+
chainIdBytes[i] = value & 255;
|
|
476
|
+
value = value >>> 8;
|
|
477
|
+
}
|
|
478
|
+
const metadata = new Uint8Array(1 + accountBytes.length + 32);
|
|
479
|
+
metadata[0] = securityZone;
|
|
480
|
+
metadata.set(accountBytes, 1);
|
|
481
|
+
metadata.set(chainIdBytes, 1 + accountBytes.length);
|
|
482
|
+
return metadata;
|
|
483
|
+
};
|
|
484
|
+
var zkVerify = async (verifierUrl, serializedBytes, address, securityZone, chainId) => {
|
|
485
|
+
const packed_list = toHexString(serializedBytes);
|
|
486
|
+
const sz_byte = new Uint8Array([securityZone]);
|
|
487
|
+
const payload = {
|
|
488
|
+
packed_list,
|
|
489
|
+
account_addr: address,
|
|
490
|
+
security_zone: sz_byte[0],
|
|
491
|
+
chain_id: chainId
|
|
492
|
+
};
|
|
493
|
+
const body = JSON.stringify(payload);
|
|
494
|
+
try {
|
|
495
|
+
const response = await fetch(`${verifierUrl}/verify`, {
|
|
496
|
+
method: "POST",
|
|
497
|
+
headers: {
|
|
498
|
+
"Content-Type": "application/json"
|
|
499
|
+
},
|
|
500
|
+
body
|
|
501
|
+
});
|
|
502
|
+
if (!response.ok) {
|
|
503
|
+
const errorBody = await response.text();
|
|
504
|
+
throw new CofhesdkError({
|
|
505
|
+
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
506
|
+
message: `HTTP error! ZK proof verification failed - ${errorBody}`
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
const json = await response.json();
|
|
510
|
+
if (json.status !== "success") {
|
|
511
|
+
throw new CofhesdkError({
|
|
512
|
+
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
513
|
+
message: `ZK proof verification response malformed - ${json.error}`
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
return json.data.map(({ ct_hash, signature, recid }) => {
|
|
517
|
+
return {
|
|
518
|
+
ct_hash,
|
|
519
|
+
signature: concatSigRecid(signature, recid)
|
|
520
|
+
};
|
|
521
|
+
});
|
|
522
|
+
} catch (e) {
|
|
523
|
+
throw new CofhesdkError({
|
|
524
|
+
code: "ZK_VERIFY_FAILED" /* ZkVerifyFailed */,
|
|
525
|
+
message: `ZK proof verification failed`,
|
|
526
|
+
cause: e instanceof Error ? e : void 0
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
var concatSigRecid = (signature, recid) => {
|
|
531
|
+
return signature + (recid + 27).toString(16).padStart(2, "0");
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
// core/encrypt/MockZkVerifierAbi.ts
|
|
535
|
+
var MockZkVerifierAbi = [
|
|
461
536
|
{
|
|
462
537
|
type: "function",
|
|
463
|
-
name: "
|
|
538
|
+
name: "exists",
|
|
464
539
|
inputs: [],
|
|
465
|
-
outputs: [{ name: "", type: "
|
|
466
|
-
stateMutability: "view"
|
|
467
|
-
},
|
|
468
|
-
{
|
|
469
|
-
type: "function",
|
|
470
|
-
name: "decodeLowLevelReversion",
|
|
471
|
-
inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
|
|
472
|
-
outputs: [{ name: "error", type: "string", internalType: "string" }],
|
|
540
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
473
541
|
stateMutability: "pure"
|
|
474
542
|
},
|
|
475
543
|
{
|
|
476
544
|
type: "function",
|
|
477
|
-
name: "
|
|
478
|
-
inputs: [
|
|
479
|
-
|
|
480
|
-
|
|
545
|
+
name: "insertCtHash",
|
|
546
|
+
inputs: [
|
|
547
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
548
|
+
{ name: "value", type: "uint256", internalType: "uint256" }
|
|
549
|
+
],
|
|
550
|
+
outputs: [],
|
|
551
|
+
stateMutability: "nonpayable"
|
|
481
552
|
},
|
|
482
553
|
{
|
|
483
554
|
type: "function",
|
|
484
|
-
name: "
|
|
555
|
+
name: "insertPackedCtHashes",
|
|
485
556
|
inputs: [
|
|
486
|
-
{ name: "
|
|
487
|
-
{ name: "
|
|
557
|
+
{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" },
|
|
558
|
+
{ name: "values", type: "uint256[]", internalType: "uint256[]" }
|
|
488
559
|
],
|
|
489
560
|
outputs: [],
|
|
490
561
|
stateMutability: "nonpayable"
|
|
491
562
|
},
|
|
492
563
|
{
|
|
493
564
|
type: "function",
|
|
494
|
-
name: "
|
|
565
|
+
name: "zkVerify",
|
|
495
566
|
inputs: [
|
|
496
|
-
{ name: "
|
|
497
|
-
{ name: "", type: "
|
|
567
|
+
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
568
|
+
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
569
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
570
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
571
|
+
{ name: "", type: "uint256", internalType: "uint256" }
|
|
572
|
+
],
|
|
573
|
+
outputs: [
|
|
498
574
|
{
|
|
499
|
-
name: "
|
|
575
|
+
name: "",
|
|
500
576
|
type: "tuple",
|
|
501
|
-
internalType: "struct
|
|
577
|
+
internalType: "struct EncryptedInput",
|
|
502
578
|
components: [
|
|
503
|
-
{ name: "
|
|
504
|
-
{ name: "
|
|
505
|
-
{ name: "
|
|
506
|
-
{ name: "
|
|
507
|
-
{
|
|
508
|
-
name: "validatorContract",
|
|
509
|
-
type: "address",
|
|
510
|
-
internalType: "address"
|
|
511
|
-
},
|
|
512
|
-
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
513
|
-
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
514
|
-
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
579
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
580
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
581
|
+
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
582
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
515
583
|
]
|
|
516
584
|
}
|
|
517
585
|
],
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
586
|
+
stateMutability: "nonpayable"
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
type: "function",
|
|
590
|
+
name: "zkVerifyCalcCtHash",
|
|
591
|
+
inputs: [
|
|
592
|
+
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
593
|
+
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
594
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
595
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
521
596
|
{ name: "", type: "uint256", internalType: "uint256" }
|
|
522
597
|
],
|
|
598
|
+
outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
|
|
523
599
|
stateMutability: "view"
|
|
524
600
|
},
|
|
525
601
|
{
|
|
526
602
|
type: "function",
|
|
527
|
-
name: "
|
|
603
|
+
name: "zkVerifyCalcCtHashesPacked",
|
|
528
604
|
inputs: [
|
|
529
|
-
{ name: "
|
|
530
|
-
{ name: "", type: "
|
|
531
|
-
{
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
internalType: "struct Permission",
|
|
535
|
-
components: [
|
|
536
|
-
{ name: "issuer", type: "address", internalType: "address" },
|
|
537
|
-
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
538
|
-
{ name: "recipient", type: "address", internalType: "address" },
|
|
539
|
-
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
540
|
-
{
|
|
541
|
-
name: "validatorContract",
|
|
542
|
-
type: "address",
|
|
543
|
-
internalType: "address"
|
|
544
|
-
},
|
|
545
|
-
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
546
|
-
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
547
|
-
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
548
|
-
]
|
|
549
|
-
}
|
|
550
|
-
],
|
|
551
|
-
outputs: [
|
|
552
|
-
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
553
|
-
{ name: "error", type: "string", internalType: "string" },
|
|
554
|
-
{ name: "", type: "bytes32", internalType: "bytes32" }
|
|
605
|
+
{ name: "values", type: "uint256[]", internalType: "uint256[]" },
|
|
606
|
+
{ name: "utypes", type: "uint8[]", internalType: "uint8[]" },
|
|
607
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
608
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
609
|
+
{ name: "chainId", type: "uint256", internalType: "uint256" }
|
|
555
610
|
],
|
|
611
|
+
outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
|
|
556
612
|
stateMutability: "view"
|
|
557
613
|
},
|
|
558
614
|
{
|
|
559
615
|
type: "function",
|
|
560
|
-
name: "
|
|
616
|
+
name: "zkVerifyPacked",
|
|
561
617
|
inputs: [
|
|
562
|
-
{ name: "
|
|
563
|
-
{ name: "
|
|
618
|
+
{ name: "values", type: "uint256[]", internalType: "uint256[]" },
|
|
619
|
+
{ name: "utypes", type: "uint8[]", internalType: "uint8[]" },
|
|
620
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
621
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
622
|
+
{ name: "chainId", type: "uint256", internalType: "uint256" }
|
|
564
623
|
],
|
|
565
|
-
outputs: [
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
name: "unseal",
|
|
578
|
-
inputs: [
|
|
579
|
-
{ name: "hashed", type: "bytes32", internalType: "bytes32" },
|
|
580
|
-
{ name: "key", type: "bytes32", internalType: "bytes32" }
|
|
624
|
+
outputs: [
|
|
625
|
+
{
|
|
626
|
+
name: "inputs",
|
|
627
|
+
type: "tuple[]",
|
|
628
|
+
internalType: "struct EncryptedInput[]",
|
|
629
|
+
components: [
|
|
630
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
631
|
+
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
632
|
+
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
633
|
+
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
634
|
+
]
|
|
635
|
+
}
|
|
581
636
|
],
|
|
582
|
-
|
|
583
|
-
stateMutability: "pure"
|
|
637
|
+
stateMutability: "nonpayable"
|
|
584
638
|
},
|
|
585
|
-
{ type: "error", name: "
|
|
586
|
-
{ type: "error", name: "SealingKeyInvalid", inputs: [] },
|
|
587
|
-
{ type: "error", name: "SealingKeyMissing", inputs: [] }
|
|
639
|
+
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
588
640
|
];
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
var
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
...permission,
|
|
598
|
-
expiration: BigInt(permission.expiration),
|
|
599
|
-
validatorId: BigInt(permission.validatorId)
|
|
600
|
-
};
|
|
601
|
-
const [allowed, error, result] = await publicClient.readContract({
|
|
602
|
-
address: MockQueryDecrypterAddress,
|
|
603
|
-
abi: MockQueryDecrypterAbi,
|
|
604
|
-
functionName: "querySealOutput",
|
|
605
|
-
args: [ctHash, BigInt(utype), permissionWithBigInts]
|
|
641
|
+
var MocksZkVerifierAddress = "0x0000000000000000000000000000000000000100";
|
|
642
|
+
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
643
|
+
var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
|
|
644
|
+
function createMockZkVerifierSigner() {
|
|
645
|
+
return createWalletClient({
|
|
646
|
+
chain: hardhat,
|
|
647
|
+
transport: http(),
|
|
648
|
+
account: privateKeyToAccount(MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY)
|
|
606
649
|
});
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
650
|
+
}
|
|
651
|
+
async function cofheMocksCheckEncryptableBits(items) {
|
|
652
|
+
let totalBits = 0;
|
|
653
|
+
for (const item of items) {
|
|
654
|
+
switch (item.utype) {
|
|
655
|
+
case 0 /* Bool */: {
|
|
656
|
+
totalBits += 1;
|
|
657
|
+
break;
|
|
658
|
+
}
|
|
659
|
+
case 2 /* Uint8 */: {
|
|
660
|
+
totalBits += 8;
|
|
661
|
+
break;
|
|
662
|
+
}
|
|
663
|
+
case 3 /* Uint16 */: {
|
|
664
|
+
totalBits += 16;
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
case 4 /* Uint32 */: {
|
|
668
|
+
totalBits += 32;
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
case 5 /* Uint64 */: {
|
|
672
|
+
totalBits += 64;
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
case 6 /* Uint128 */: {
|
|
676
|
+
totalBits += 128;
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
case 7 /* Uint160 */: {
|
|
680
|
+
totalBits += 160;
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
612
684
|
}
|
|
613
|
-
if (
|
|
685
|
+
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
614
686
|
throw new CofhesdkError({
|
|
615
|
-
code: "
|
|
616
|
-
message: `
|
|
687
|
+
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
688
|
+
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
689
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
690
|
+
context: {
|
|
691
|
+
totalBits,
|
|
692
|
+
maxBits: MAX_ENCRYPTABLE_BITS,
|
|
693
|
+
items
|
|
694
|
+
}
|
|
617
695
|
});
|
|
618
696
|
}
|
|
619
|
-
const sealedBigInt = BigInt(result);
|
|
620
|
-
const sealingKeyBigInt = BigInt(permission.sealingKey);
|
|
621
|
-
const unsealed = sealedBigInt ^ sealingKeyBigInt;
|
|
622
|
-
return unsealed;
|
|
623
697
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
permit: permission
|
|
634
|
-
};
|
|
698
|
+
async function calcCtHashes(items, account, securityZone, publicClient) {
|
|
699
|
+
const calcCtHashesArgs = [
|
|
700
|
+
items.map(({ data }) => BigInt(data)),
|
|
701
|
+
items.map(({ utype }) => utype),
|
|
702
|
+
account,
|
|
703
|
+
securityZone,
|
|
704
|
+
BigInt(hardhat.id)
|
|
705
|
+
];
|
|
706
|
+
let ctHashes;
|
|
635
707
|
try {
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
body: JSON.stringify(body)
|
|
708
|
+
ctHashes = await publicClient.readContract({
|
|
709
|
+
address: MocksZkVerifierAddress,
|
|
710
|
+
abi: MockZkVerifierAbi,
|
|
711
|
+
functionName: "zkVerifyCalcCtHashesPacked",
|
|
712
|
+
args: calcCtHashesArgs
|
|
642
713
|
});
|
|
643
|
-
|
|
644
|
-
sealed = sealOutputResult.sealed;
|
|
645
|
-
errorMessage = sealOutputResult.error_message;
|
|
646
|
-
} catch (e) {
|
|
714
|
+
} catch (err) {
|
|
647
715
|
throw new CofhesdkError({
|
|
648
|
-
code: "
|
|
649
|
-
message: `
|
|
650
|
-
|
|
651
|
-
cause: e instanceof Error ? e : void 0,
|
|
716
|
+
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
717
|
+
message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
|
|
718
|
+
cause: err instanceof Error ? err : void 0,
|
|
652
719
|
context: {
|
|
653
|
-
|
|
654
|
-
|
|
720
|
+
address: MocksZkVerifierAddress,
|
|
721
|
+
items,
|
|
722
|
+
account,
|
|
723
|
+
securityZone,
|
|
724
|
+
publicClient,
|
|
725
|
+
calcCtHashesArgs
|
|
655
726
|
}
|
|
656
727
|
});
|
|
657
728
|
}
|
|
658
|
-
if (
|
|
729
|
+
if (ctHashes.length !== items.length) {
|
|
659
730
|
throw new CofhesdkError({
|
|
660
|
-
code: "
|
|
661
|
-
message: `
|
|
731
|
+
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
732
|
+
message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
|
|
662
733
|
context: {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
734
|
+
items,
|
|
735
|
+
account,
|
|
736
|
+
securityZone,
|
|
737
|
+
publicClient,
|
|
738
|
+
calcCtHashesArgs,
|
|
739
|
+
ctHashes
|
|
666
740
|
}
|
|
667
741
|
});
|
|
668
742
|
}
|
|
669
|
-
return
|
|
743
|
+
return items.map((item, index) => ({
|
|
744
|
+
...item,
|
|
745
|
+
ctHash: ctHashes[index]
|
|
746
|
+
}));
|
|
670
747
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
748
|
+
async function insertCtHashes(items, walletClient) {
|
|
749
|
+
const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
|
|
750
|
+
try {
|
|
751
|
+
const account = walletClient.account;
|
|
752
|
+
await walletClient.writeContract({
|
|
753
|
+
address: MocksZkVerifierAddress,
|
|
754
|
+
abi: MockZkVerifierAbi,
|
|
755
|
+
functionName: "insertPackedCtHashes",
|
|
756
|
+
args: insertPackedCtHashesArgs,
|
|
757
|
+
chain: hardhat,
|
|
758
|
+
account
|
|
759
|
+
});
|
|
760
|
+
} catch (err) {
|
|
761
|
+
throw new CofhesdkError({
|
|
762
|
+
code: "ZK_MOCKS_INSERT_CT_HASHES_FAILED" /* ZkMocksInsertCtHashesFailed */,
|
|
763
|
+
message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
|
|
764
|
+
cause: err instanceof Error ? err : void 0,
|
|
765
|
+
context: {
|
|
766
|
+
items,
|
|
767
|
+
walletClient,
|
|
768
|
+
insertPackedCtHashesArgs
|
|
769
|
+
}
|
|
686
770
|
});
|
|
687
|
-
this.ctHash = params.ctHash;
|
|
688
|
-
this.utype = params.utype;
|
|
689
|
-
this.permitHash = params.permitHash;
|
|
690
|
-
this.permit = params.permit;
|
|
691
|
-
}
|
|
692
|
-
/**
|
|
693
|
-
* @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
|
|
694
|
-
*
|
|
695
|
-
* If not provided, the chainId will be fetched from the connected publicClient.
|
|
696
|
-
*
|
|
697
|
-
* Example:
|
|
698
|
-
* ```typescript
|
|
699
|
-
* const unsealed = await decryptHandle(ctHash, utype)
|
|
700
|
-
* .setChainId(11155111)
|
|
701
|
-
* .decrypt();
|
|
702
|
-
* ```
|
|
703
|
-
*
|
|
704
|
-
* @returns The chainable DecryptHandlesBuilder instance.
|
|
705
|
-
*/
|
|
706
|
-
setChainId(chainId) {
|
|
707
|
-
this.chainId = chainId;
|
|
708
|
-
return this;
|
|
709
|
-
}
|
|
710
|
-
getChainId() {
|
|
711
|
-
return this.chainId;
|
|
712
771
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
*/
|
|
727
|
-
setAccount(account) {
|
|
728
|
-
this.account = account;
|
|
729
|
-
return this;
|
|
730
|
-
}
|
|
731
|
-
getAccount() {
|
|
732
|
-
return this.account;
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
|
|
736
|
-
*
|
|
737
|
-
* If not provided, the active permit for the chainId and account will be used.
|
|
738
|
-
* If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
|
|
739
|
-
*
|
|
740
|
-
* Example:
|
|
741
|
-
* ```typescript
|
|
742
|
-
* const unsealed = await decryptHandle(ctHash, utype)
|
|
743
|
-
* .setPermitHash('0x1234567890123456789012345678901234567890')
|
|
744
|
-
* .decrypt();
|
|
745
|
-
* ```
|
|
746
|
-
*
|
|
747
|
-
* @returns The chainable DecryptHandlesBuilder instance.
|
|
748
|
-
*/
|
|
749
|
-
setPermitHash(permitHash) {
|
|
750
|
-
this.permitHash = permitHash;
|
|
751
|
-
return this;
|
|
752
|
-
}
|
|
753
|
-
getPermitHash() {
|
|
754
|
-
return this.permitHash;
|
|
755
|
-
}
|
|
756
|
-
/**
|
|
757
|
-
* @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
|
|
758
|
-
*
|
|
759
|
-
* If not provided, the permit will be determined by chainId, account, and permitHash.
|
|
760
|
-
*
|
|
761
|
-
* Example:
|
|
762
|
-
* ```typescript
|
|
763
|
-
* const unsealed = await decryptHandle(ctHash, utype)
|
|
764
|
-
* .setPermit(permit)
|
|
765
|
-
* .decrypt();
|
|
766
|
-
* ```
|
|
767
|
-
*
|
|
768
|
-
* @returns The chainable DecryptHandlesBuilder instance.
|
|
769
|
-
*/
|
|
770
|
-
setPermit(permit) {
|
|
771
|
-
this.permit = permit;
|
|
772
|
-
return this;
|
|
773
|
-
}
|
|
774
|
-
getPermit() {
|
|
775
|
-
return this.permit;
|
|
776
|
-
}
|
|
777
|
-
getThresholdNetworkUrl(chainId) {
|
|
778
|
-
const config = this.getConfigOrThrow();
|
|
779
|
-
return getThresholdNetworkUrlOrThrow(config, chainId);
|
|
780
|
-
}
|
|
781
|
-
validateUtypeOrThrow() {
|
|
782
|
-
if (!isValidUtype(this.utype))
|
|
783
|
-
throw new CofhesdkError({
|
|
784
|
-
code: "INVALID_UTYPE" /* InvalidUtype */,
|
|
785
|
-
message: `Invalid utype to decrypt to`,
|
|
786
|
-
context: {
|
|
787
|
-
utype: this.utype
|
|
788
|
-
}
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
|
-
async getResolvedPermit() {
|
|
792
|
-
if (this.permit)
|
|
793
|
-
return this.permit;
|
|
794
|
-
const chainId = await this.getChainIdOrThrow();
|
|
795
|
-
const account = await this.getAccountOrThrow();
|
|
796
|
-
if (this.permitHash) {
|
|
797
|
-
const permit2 = await permits.getPermit(chainId, account, this.permitHash);
|
|
798
|
-
if (!permit2) {
|
|
799
|
-
throw new CofhesdkError({
|
|
800
|
-
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
801
|
-
message: `Permit with hash <${this.permitHash}> not found for account <${account}> and chainId <${chainId}>`,
|
|
802
|
-
hint: "Ensure the permit exists and is valid.",
|
|
803
|
-
context: {
|
|
804
|
-
chainId,
|
|
805
|
-
account,
|
|
806
|
-
permitHash: this.permitHash
|
|
807
|
-
}
|
|
808
|
-
});
|
|
772
|
+
}
|
|
773
|
+
async function createProofSignatures(items, securityZone) {
|
|
774
|
+
let signatures = [];
|
|
775
|
+
let encInputSignerClient;
|
|
776
|
+
try {
|
|
777
|
+
encInputSignerClient = createMockZkVerifierSigner();
|
|
778
|
+
} catch (err) {
|
|
779
|
+
throw new CofhesdkError({
|
|
780
|
+
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
781
|
+
message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
|
|
782
|
+
cause: err instanceof Error ? err : void 0,
|
|
783
|
+
context: {
|
|
784
|
+
MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY
|
|
809
785
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
account
|
|
821
|
-
}
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
try {
|
|
789
|
+
for (const item of items) {
|
|
790
|
+
const packedData = encodePacked(["uint256", "int32", "uint8"], [BigInt(item.data), securityZone, item.utype]);
|
|
791
|
+
const messageHash = keccak256(packedData);
|
|
792
|
+
const ethSignedHash = hashMessage({ raw: toBytes(messageHash) });
|
|
793
|
+
const signature = await encInputSignerClient.signMessage({
|
|
794
|
+
message: { raw: toBytes(ethSignedHash) },
|
|
795
|
+
account: encInputSignerClient.account
|
|
822
796
|
});
|
|
797
|
+
signatures.push(signature);
|
|
823
798
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.getPublicClientOrThrow(), mocksSealOutputDelay);
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
836
|
-
*/
|
|
837
|
-
async productionSealOutput(chainId, permit) {
|
|
838
|
-
const thresholdNetworkUrl = this.getThresholdNetworkUrl(chainId);
|
|
839
|
-
const permission = PermitUtils.getPermission(permit, true);
|
|
840
|
-
const sealed = await tnSealOutput(this.ctHash, chainId, permission, thresholdNetworkUrl);
|
|
841
|
-
return PermitUtils.unseal(permit, sealed);
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
|
|
845
|
-
*
|
|
846
|
-
* This will:
|
|
847
|
-
* - Use a permit based on provided permit OR chainId + account + permitHash
|
|
848
|
-
* - Check permit validity
|
|
849
|
-
* - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
|
|
850
|
-
* - Unseal the sealed item with the permit
|
|
851
|
-
* - Return the unsealed item
|
|
852
|
-
*
|
|
853
|
-
* Example:
|
|
854
|
-
* ```typescript
|
|
855
|
-
* const unsealed = await decryptHandle(ctHash, utype)
|
|
856
|
-
* .setChainId(11155111) // optional
|
|
857
|
-
* .setAccount('0x123...890') // optional
|
|
858
|
-
* .decrypt(); // execute
|
|
859
|
-
* ```
|
|
860
|
-
*
|
|
861
|
-
* @returns The unsealed item.
|
|
862
|
-
*/
|
|
863
|
-
decrypt() {
|
|
864
|
-
return resultWrapper(async () => {
|
|
865
|
-
await this.requireConnectedOrThrow();
|
|
866
|
-
this.validateUtypeOrThrow();
|
|
867
|
-
const permit = await this.getResolvedPermit();
|
|
868
|
-
await PermitUtils.validate(permit);
|
|
869
|
-
const chainId = permit._signedDomain.chainId;
|
|
870
|
-
let unsealed;
|
|
871
|
-
if (chainId === hardhat.id) {
|
|
872
|
-
unsealed = await this.mocksSealOutput(permit);
|
|
873
|
-
} else {
|
|
874
|
-
unsealed = await this.productionSealOutput(chainId, permit);
|
|
799
|
+
} catch (err) {
|
|
800
|
+
throw new CofhesdkError({
|
|
801
|
+
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
802
|
+
message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
|
|
803
|
+
cause: err instanceof Error ? err : void 0,
|
|
804
|
+
context: {
|
|
805
|
+
items,
|
|
806
|
+
securityZone
|
|
875
807
|
}
|
|
876
|
-
return convertViaUtype(this.utype, unsealed);
|
|
877
808
|
});
|
|
878
809
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
// core/encrypt/zkPackProveVerify.ts
|
|
882
|
-
var MAX_UINT8 = 255n;
|
|
883
|
-
var MAX_UINT16 = 65535n;
|
|
884
|
-
var MAX_UINT32 = 4294967295n;
|
|
885
|
-
var MAX_UINT64 = 18446744073709551615n;
|
|
886
|
-
var MAX_UINT128 = 340282366920938463463374607431768211455n;
|
|
887
|
-
var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
|
|
888
|
-
var MAX_ENCRYPTABLE_BITS = 2048;
|
|
889
|
-
var zkPack = (items, builder) => {
|
|
890
|
-
let totalBits = 0;
|
|
891
|
-
for (const item of items) {
|
|
892
|
-
switch (item.utype) {
|
|
893
|
-
case 0 /* Bool */: {
|
|
894
|
-
builder.push_boolean(item.data);
|
|
895
|
-
totalBits += 1;
|
|
896
|
-
break;
|
|
897
|
-
}
|
|
898
|
-
case 2 /* Uint8 */: {
|
|
899
|
-
const bint = toBigIntOrThrow(item.data);
|
|
900
|
-
validateBigIntInRange(bint, MAX_UINT8);
|
|
901
|
-
builder.push_u8(parseInt(bint.toString()));
|
|
902
|
-
totalBits += 8;
|
|
903
|
-
break;
|
|
904
|
-
}
|
|
905
|
-
case 3 /* Uint16 */: {
|
|
906
|
-
const bint = toBigIntOrThrow(item.data);
|
|
907
|
-
validateBigIntInRange(bint, MAX_UINT16);
|
|
908
|
-
builder.push_u16(parseInt(bint.toString()));
|
|
909
|
-
totalBits += 16;
|
|
910
|
-
break;
|
|
911
|
-
}
|
|
912
|
-
case 4 /* Uint32 */: {
|
|
913
|
-
const bint = toBigIntOrThrow(item.data);
|
|
914
|
-
validateBigIntInRange(bint, MAX_UINT32);
|
|
915
|
-
builder.push_u32(parseInt(bint.toString()));
|
|
916
|
-
totalBits += 32;
|
|
917
|
-
break;
|
|
918
|
-
}
|
|
919
|
-
case 5 /* Uint64 */: {
|
|
920
|
-
const bint = toBigIntOrThrow(item.data);
|
|
921
|
-
validateBigIntInRange(bint, MAX_UINT64);
|
|
922
|
-
builder.push_u64(bint);
|
|
923
|
-
totalBits += 64;
|
|
924
|
-
break;
|
|
925
|
-
}
|
|
926
|
-
case 6 /* Uint128 */: {
|
|
927
|
-
const bint = toBigIntOrThrow(item.data);
|
|
928
|
-
validateBigIntInRange(bint, MAX_UINT128);
|
|
929
|
-
builder.push_u128(bint);
|
|
930
|
-
totalBits += 128;
|
|
931
|
-
break;
|
|
932
|
-
}
|
|
933
|
-
case 7 /* Uint160 */: {
|
|
934
|
-
const bint = toBigIntOrThrow(item.data);
|
|
935
|
-
validateBigIntInRange(bint, MAX_UINT160);
|
|
936
|
-
builder.push_u160(bint);
|
|
937
|
-
totalBits += 160;
|
|
938
|
-
break;
|
|
939
|
-
}
|
|
940
|
-
default: {
|
|
941
|
-
throw new CofhesdkError({
|
|
942
|
-
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
943
|
-
message: `Invalid utype: ${item.utype}`,
|
|
944
|
-
hint: `Ensure that the utype is valid, using the Encryptable type, for example: Encryptable.uint128(100n)`,
|
|
945
|
-
context: {
|
|
946
|
-
item
|
|
947
|
-
}
|
|
948
|
-
});
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
810
|
+
if (signatures.length !== items.length) {
|
|
953
811
|
throw new CofhesdkError({
|
|
954
|
-
code: "
|
|
955
|
-
message: `
|
|
956
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
812
|
+
code: "ZK_MOCKS_CREATE_PROOF_SIGNATURE_FAILED" /* ZkMocksCreateProofSignatureFailed */,
|
|
813
|
+
message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
|
|
957
814
|
context: {
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
items
|
|
815
|
+
items,
|
|
816
|
+
securityZone
|
|
961
817
|
}
|
|
962
818
|
});
|
|
963
819
|
}
|
|
964
|
-
return
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
820
|
+
return signatures;
|
|
821
|
+
}
|
|
822
|
+
async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
|
|
823
|
+
const _walletClient = zkvWalletClient ?? createMockZkVerifierSigner();
|
|
824
|
+
const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
|
|
825
|
+
await insertCtHashes(encryptableItems, _walletClient);
|
|
826
|
+
const signatures = await createProofSignatures(encryptableItems, securityZone);
|
|
827
|
+
return encryptableItems.map((item, index) => ({
|
|
828
|
+
ct_hash: item.ctHash.toString(),
|
|
829
|
+
signature: signatures[index]
|
|
830
|
+
}));
|
|
831
|
+
}
|
|
832
|
+
var CofhesdkConfigSchema = z.object({
|
|
833
|
+
/** Environment that the SDK is running in */
|
|
834
|
+
environment: z.enum(["node", "hardhat", "web", "react"]).optional().default("node"),
|
|
835
|
+
/** List of supported chain configurations */
|
|
836
|
+
supportedChains: z.array(z.custom()),
|
|
837
|
+
/** How permits are generated */
|
|
838
|
+
permitGeneration: z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
|
|
839
|
+
/** Default permit expiration in seconds, default is 30 days */
|
|
840
|
+
defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
|
|
841
|
+
/** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
|
|
842
|
+
fheKeyStorage: z.object({
|
|
843
|
+
getItem: z.function().args(z.string()).returns(z.promise(z.any())),
|
|
844
|
+
setItem: z.function().args(z.string(), z.any()).returns(z.promise(z.void())),
|
|
845
|
+
removeItem: z.function().args(z.string()).returns(z.promise(z.void()))
|
|
846
|
+
}).or(z.null()).default(null),
|
|
847
|
+
/** Whether to use Web Workers for ZK proof generation (web platform only) */
|
|
848
|
+
useWorkers: z.boolean().optional().default(true),
|
|
849
|
+
/** Mocks configs */
|
|
850
|
+
mocks: z.object({
|
|
851
|
+
sealOutputDelay: z.number().optional().default(0)
|
|
852
|
+
}).optional().default({ sealOutputDelay: 0 }),
|
|
853
|
+
/** Internal configuration */
|
|
854
|
+
_internal: z.object({
|
|
855
|
+
zkvWalletClient: z.any().optional()
|
|
856
|
+
}).optional()
|
|
857
|
+
});
|
|
858
|
+
function createCofhesdkConfigBase(config) {
|
|
859
|
+
const result = CofhesdkConfigSchema.safeParse(config);
|
|
860
|
+
if (!result.success) {
|
|
861
|
+
throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
|
|
988
862
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
return metadata;
|
|
863
|
+
return result.data;
|
|
864
|
+
}
|
|
865
|
+
var getCofhesdkConfigItem = (config, key) => {
|
|
866
|
+
return config[key];
|
|
994
867
|
};
|
|
995
|
-
|
|
996
|
-
const
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
const response = await fetch(`${verifierUrl}/verify`, {
|
|
1007
|
-
method: "POST",
|
|
1008
|
-
headers: {
|
|
1009
|
-
"Content-Type": "application/json"
|
|
1010
|
-
},
|
|
1011
|
-
body
|
|
868
|
+
function getSupportedChainOrThrow(config, chainId) {
|
|
869
|
+
const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
|
|
870
|
+
if (!supportedChain) {
|
|
871
|
+
throw new CofhesdkError({
|
|
872
|
+
code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
|
|
873
|
+
message: `Config does not support chain <${chainId}>`,
|
|
874
|
+
hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
|
|
875
|
+
context: {
|
|
876
|
+
chainId,
|
|
877
|
+
supportedChainIds: config.supportedChains.map((c) => c.id)
|
|
878
|
+
}
|
|
1012
879
|
});
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
return json.data.map(({ ct_hash, signature, recid }) => {
|
|
1028
|
-
return {
|
|
1029
|
-
ct_hash,
|
|
1030
|
-
signature: concatSigRecid(signature, recid)
|
|
1031
|
-
};
|
|
880
|
+
}
|
|
881
|
+
return supportedChain;
|
|
882
|
+
}
|
|
883
|
+
function getCoFheUrlOrThrow(config, chainId) {
|
|
884
|
+
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
885
|
+
const url = supportedChain.coFheUrl;
|
|
886
|
+
if (!url) {
|
|
887
|
+
throw new CofhesdkError({
|
|
888
|
+
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
889
|
+
message: `CoFHE URL is not configured for chain <${chainId}>`,
|
|
890
|
+
hint: "Ensure this chain config includes a coFheUrl property.",
|
|
891
|
+
context: { chainId }
|
|
1032
892
|
});
|
|
1033
|
-
}
|
|
893
|
+
}
|
|
894
|
+
return url;
|
|
895
|
+
}
|
|
896
|
+
function getZkVerifierUrlOrThrow(config, chainId) {
|
|
897
|
+
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
898
|
+
const url = supportedChain.verifierUrl;
|
|
899
|
+
if (!url) {
|
|
1034
900
|
throw new CofhesdkError({
|
|
1035
|
-
code: "
|
|
1036
|
-
message: `ZK
|
|
1037
|
-
|
|
901
|
+
code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
|
|
902
|
+
message: `ZK verifier URL is not configured for chain <${chainId}>`,
|
|
903
|
+
hint: "Ensure this chain config includes a verifierUrl property.",
|
|
904
|
+
context: { chainId }
|
|
1038
905
|
});
|
|
1039
906
|
}
|
|
907
|
+
return url;
|
|
908
|
+
}
|
|
909
|
+
function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
910
|
+
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
911
|
+
const url = supportedChain.thresholdNetworkUrl;
|
|
912
|
+
if (!url) {
|
|
913
|
+
throw new CofhesdkError({
|
|
914
|
+
code: "THRESHOLD_NETWORK_URL_UNINITIALIZED" /* ThresholdNetworkUrlUninitialized */,
|
|
915
|
+
message: `Threshold network URL is not configured for chain <${chainId}>`,
|
|
916
|
+
hint: "Ensure this chain config includes a thresholdNetworkUrl property.",
|
|
917
|
+
context: { chainId }
|
|
918
|
+
});
|
|
919
|
+
}
|
|
920
|
+
return url;
|
|
921
|
+
}
|
|
922
|
+
function isValidPersistedState(state) {
|
|
923
|
+
if (state && typeof state === "object") {
|
|
924
|
+
if ("fhe" in state && "crs" in state) {
|
|
925
|
+
return true;
|
|
926
|
+
} else {
|
|
927
|
+
throw new Error(
|
|
928
|
+
"Invalid persisted state structure for KeysStore. Is object but doesn't contain required fields 'fhe' and 'crs'."
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
var DEFAULT_KEYS_STORE = {
|
|
935
|
+
fhe: {},
|
|
936
|
+
crs: {}
|
|
1040
937
|
};
|
|
1041
|
-
|
|
1042
|
-
return
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
{ name: "user", type: "address", internalType: "address" },
|
|
1081
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1082
|
-
{ name: "", type: "uint256", internalType: "uint256" }
|
|
1083
|
-
],
|
|
1084
|
-
outputs: [
|
|
1085
|
-
{
|
|
1086
|
-
name: "",
|
|
1087
|
-
type: "tuple",
|
|
1088
|
-
internalType: "struct EncryptedInput",
|
|
1089
|
-
components: [
|
|
1090
|
-
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
1091
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1092
|
-
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
1093
|
-
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
1094
|
-
]
|
|
1095
|
-
}
|
|
1096
|
-
],
|
|
1097
|
-
stateMutability: "nonpayable"
|
|
1098
|
-
},
|
|
1099
|
-
{
|
|
1100
|
-
type: "function",
|
|
1101
|
-
name: "zkVerifyCalcCtHash",
|
|
1102
|
-
inputs: [
|
|
1103
|
-
{ name: "value", type: "uint256", internalType: "uint256" },
|
|
1104
|
-
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
1105
|
-
{ name: "user", type: "address", internalType: "address" },
|
|
1106
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1107
|
-
{ name: "", type: "uint256", internalType: "uint256" }
|
|
1108
|
-
],
|
|
1109
|
-
outputs: [{ name: "ctHash", type: "uint256", internalType: "uint256" }],
|
|
1110
|
-
stateMutability: "view"
|
|
1111
|
-
},
|
|
1112
|
-
{
|
|
1113
|
-
type: "function",
|
|
1114
|
-
name: "zkVerifyCalcCtHashesPacked",
|
|
1115
|
-
inputs: [
|
|
1116
|
-
{ name: "values", type: "uint256[]", internalType: "uint256[]" },
|
|
1117
|
-
{ name: "utypes", type: "uint8[]", internalType: "uint8[]" },
|
|
1118
|
-
{ name: "user", type: "address", internalType: "address" },
|
|
1119
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1120
|
-
{ name: "chainId", type: "uint256", internalType: "uint256" }
|
|
1121
|
-
],
|
|
1122
|
-
outputs: [{ name: "ctHashes", type: "uint256[]", internalType: "uint256[]" }],
|
|
1123
|
-
stateMutability: "view"
|
|
1124
|
-
},
|
|
1125
|
-
{
|
|
1126
|
-
type: "function",
|
|
1127
|
-
name: "zkVerifyPacked",
|
|
1128
|
-
inputs: [
|
|
1129
|
-
{ name: "values", type: "uint256[]", internalType: "uint256[]" },
|
|
1130
|
-
{ name: "utypes", type: "uint8[]", internalType: "uint8[]" },
|
|
1131
|
-
{ name: "user", type: "address", internalType: "address" },
|
|
1132
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1133
|
-
{ name: "chainId", type: "uint256", internalType: "uint256" }
|
|
1134
|
-
],
|
|
1135
|
-
outputs: [
|
|
1136
|
-
{
|
|
1137
|
-
name: "inputs",
|
|
1138
|
-
type: "tuple[]",
|
|
1139
|
-
internalType: "struct EncryptedInput[]",
|
|
1140
|
-
components: [
|
|
1141
|
-
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
1142
|
-
{ name: "securityZone", type: "uint8", internalType: "uint8" },
|
|
1143
|
-
{ name: "utype", type: "uint8", internalType: "uint8" },
|
|
1144
|
-
{ name: "signature", type: "bytes", internalType: "bytes" }
|
|
1145
|
-
]
|
|
1146
|
-
}
|
|
1147
|
-
],
|
|
1148
|
-
stateMutability: "nonpayable"
|
|
1149
|
-
},
|
|
1150
|
-
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
1151
|
-
];
|
|
1152
|
-
var MocksZkVerifierAddress = "0x0000000000000000000000000000000000000100";
|
|
1153
|
-
var MocksEncryptedInputSignerPkey = "0x6c8d7f768a6bb4aafe85e8a2f5a9680355239c7e14646ed62b044e39de154512";
|
|
1154
|
-
async function cofheMocksCheckEncryptableBits(items) {
|
|
1155
|
-
let totalBits = 0;
|
|
1156
|
-
for (const item of items) {
|
|
1157
|
-
switch (item.utype) {
|
|
1158
|
-
case 0 /* Bool */: {
|
|
1159
|
-
totalBits += 1;
|
|
1160
|
-
break;
|
|
1161
|
-
}
|
|
1162
|
-
case 2 /* Uint8 */: {
|
|
1163
|
-
totalBits += 8;
|
|
1164
|
-
break;
|
|
1165
|
-
}
|
|
1166
|
-
case 3 /* Uint16 */: {
|
|
1167
|
-
totalBits += 16;
|
|
1168
|
-
break;
|
|
1169
|
-
}
|
|
1170
|
-
case 4 /* Uint32 */: {
|
|
1171
|
-
totalBits += 32;
|
|
1172
|
-
break;
|
|
1173
|
-
}
|
|
1174
|
-
case 5 /* Uint64 */: {
|
|
1175
|
-
totalBits += 64;
|
|
1176
|
-
break;
|
|
1177
|
-
}
|
|
1178
|
-
case 6 /* Uint128 */: {
|
|
1179
|
-
totalBits += 128;
|
|
1180
|
-
break;
|
|
1181
|
-
}
|
|
1182
|
-
case 7 /* Uint160 */: {
|
|
1183
|
-
totalBits += 160;
|
|
1184
|
-
break;
|
|
1185
|
-
}
|
|
938
|
+
function isStoreWithPersist(store) {
|
|
939
|
+
return "persist" in store;
|
|
940
|
+
}
|
|
941
|
+
function createKeysStore(storage) {
|
|
942
|
+
const keysStore = storage ? createStoreWithPersit(storage) : createStore()(() => ({
|
|
943
|
+
fhe: {},
|
|
944
|
+
crs: {}
|
|
945
|
+
}));
|
|
946
|
+
const getFheKey = (chainId, securityZone = 0) => {
|
|
947
|
+
if (chainId == null || securityZone == null)
|
|
948
|
+
return void 0;
|
|
949
|
+
const stored = keysStore.getState().fhe[chainId]?.[securityZone];
|
|
950
|
+
return stored;
|
|
951
|
+
};
|
|
952
|
+
const getCrs = (chainId) => {
|
|
953
|
+
if (chainId == null)
|
|
954
|
+
return void 0;
|
|
955
|
+
const stored = keysStore.getState().crs[chainId];
|
|
956
|
+
return stored;
|
|
957
|
+
};
|
|
958
|
+
const setFheKey = (chainId, securityZone, key) => {
|
|
959
|
+
keysStore.setState(
|
|
960
|
+
produce((state) => {
|
|
961
|
+
if (state.fhe[chainId] == null)
|
|
962
|
+
state.fhe[chainId] = {};
|
|
963
|
+
state.fhe[chainId][securityZone] = key;
|
|
964
|
+
})
|
|
965
|
+
);
|
|
966
|
+
};
|
|
967
|
+
const setCrs = (chainId, crs) => {
|
|
968
|
+
keysStore.setState(
|
|
969
|
+
produce((state) => {
|
|
970
|
+
state.crs[chainId] = crs;
|
|
971
|
+
})
|
|
972
|
+
);
|
|
973
|
+
};
|
|
974
|
+
const clearKeysStorage = async () => {
|
|
975
|
+
if (storage) {
|
|
976
|
+
await storage.removeItem("cofhesdk-keys");
|
|
1186
977
|
}
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
978
|
+
};
|
|
979
|
+
const rehydrateKeysStore = async () => {
|
|
980
|
+
if (!isStoreWithPersist(keysStore))
|
|
981
|
+
return;
|
|
982
|
+
if (keysStore.persist.hasHydrated())
|
|
983
|
+
return;
|
|
984
|
+
await keysStore.persist.rehydrate();
|
|
985
|
+
};
|
|
986
|
+
return {
|
|
987
|
+
store: keysStore,
|
|
988
|
+
getFheKey,
|
|
989
|
+
getCrs,
|
|
990
|
+
setFheKey,
|
|
991
|
+
setCrs,
|
|
992
|
+
clearKeysStorage,
|
|
993
|
+
rehydrateKeysStore
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
function createStoreWithPersit(storage) {
|
|
997
|
+
const result = createStore()(
|
|
998
|
+
persist(() => DEFAULT_KEYS_STORE, {
|
|
999
|
+
// because earleir tests were written with on-init hydration skipped (due to the error suppression in zustand), returning this flag to fix test (i.e. KeyStore > Storage Utilities > should rehydrate keys store)
|
|
1000
|
+
skipHydration: true,
|
|
1001
|
+
// if onRehydrateStorage is not passed here, the errors thrown by storage layer are swallowed by zustand here: https://github.com/pmndrs/zustand/blob/39a391b6c1ff9aa89b81694d9bdb21da37dd4ac6/src/middleware/persist.ts#L321
|
|
1002
|
+
onRehydrateStorage: () => (_state, _error) => {
|
|
1003
|
+
if (_error)
|
|
1004
|
+
throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
|
|
1005
|
+
},
|
|
1006
|
+
name: "cofhesdk-keys",
|
|
1007
|
+
storage: createJSONStorage(() => storage),
|
|
1008
|
+
merge: (persistedState, currentState) => {
|
|
1009
|
+
const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
|
|
1010
|
+
const current = currentState;
|
|
1011
|
+
const mergedFhe = { ...persisted.fhe };
|
|
1012
|
+
const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
|
|
1013
|
+
for (const chainId of allChainIds) {
|
|
1014
|
+
const persistedZones = persisted.fhe[chainId] || {};
|
|
1015
|
+
const currentZones = current.fhe[chainId] || {};
|
|
1016
|
+
mergedFhe[chainId] = { ...persistedZones, ...currentZones };
|
|
1017
|
+
}
|
|
1018
|
+
const mergedCrs = { ...persisted.crs, ...current.crs };
|
|
1019
|
+
return {
|
|
1020
|
+
fhe: mergedFhe,
|
|
1021
|
+
crs: mergedCrs
|
|
1022
|
+
};
|
|
1197
1023
|
}
|
|
1198
|
-
})
|
|
1199
|
-
|
|
1024
|
+
})
|
|
1025
|
+
);
|
|
1026
|
+
return result;
|
|
1200
1027
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
BigInt(hardhat$1.id)
|
|
1208
|
-
];
|
|
1209
|
-
let ctHashes;
|
|
1028
|
+
|
|
1029
|
+
// core/fetchKeys.ts
|
|
1030
|
+
var PUBLIC_KEY_LENGTH_MIN = 15e3;
|
|
1031
|
+
var checkKeyValidity = (key, serializer) => {
|
|
1032
|
+
if (key == null || key.length === 0)
|
|
1033
|
+
return [false, `Key is null or empty <${key}>`];
|
|
1210
1034
|
try {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
abi: MockZkVerifierAbi,
|
|
1214
|
-
functionName: "zkVerifyCalcCtHashesPacked",
|
|
1215
|
-
args: calcCtHashesArgs
|
|
1216
|
-
});
|
|
1035
|
+
serializer(key);
|
|
1036
|
+
return [true, `Key is valid`];
|
|
1217
1037
|
} catch (err) {
|
|
1218
|
-
|
|
1219
|
-
code: "ZK_MOCKS_CALC_CT_HASHES_FAILED" /* ZkMocksCalcCtHashesFailed */,
|
|
1220
|
-
message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
|
|
1221
|
-
cause: err instanceof Error ? err : void 0,
|
|
1222
|
-
context: {
|
|
1223
|
-
address: MocksZkVerifierAddress,
|
|
1224
|
-
items,
|
|
1225
|
-
account,
|
|
1226
|
-
securityZone,
|
|
1227
|
-
publicClient,
|
|
1228
|
-
calcCtHashesArgs
|
|
1229
|
-
}
|
|
1230
|
-
});
|
|
1038
|
+
return [false, `Serialization failed <${err}> key length <${key.length}>`];
|
|
1231
1039
|
}
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1040
|
+
};
|
|
1041
|
+
var fetchFhePublicKey = async (coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage) => {
|
|
1042
|
+
const storedKey = keysStorage?.getFheKey(chainId, securityZone);
|
|
1043
|
+
const [storedKeyValid] = checkKeyValidity(storedKey, tfhePublicKeyDeserializer);
|
|
1044
|
+
if (storedKeyValid)
|
|
1045
|
+
return [storedKey, false];
|
|
1046
|
+
let pk_data = void 0;
|
|
1047
|
+
try {
|
|
1048
|
+
const pk_res = await fetch(`${coFheUrl}/GetNetworkPublicKey`, {
|
|
1049
|
+
method: "POST",
|
|
1050
|
+
headers: {
|
|
1051
|
+
"Content-Type": "application/json"
|
|
1052
|
+
},
|
|
1053
|
+
body: JSON.stringify({ securityZone })
|
|
1244
1054
|
});
|
|
1055
|
+
const json = await pk_res.json();
|
|
1056
|
+
pk_data = json.publicKey;
|
|
1057
|
+
} catch (err) {
|
|
1058
|
+
throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
|
|
1059
|
+
}
|
|
1060
|
+
if (pk_data == null || typeof pk_data !== "string") {
|
|
1061
|
+
throw new Error(`Error fetching FHE publicKey; fetched result invalid: missing or not a string`);
|
|
1062
|
+
}
|
|
1063
|
+
if (pk_data === "0x") {
|
|
1064
|
+
throw new Error("Error fetching FHE publicKey; provided chain is not FHE enabled / not found");
|
|
1065
|
+
}
|
|
1066
|
+
if (pk_data.length < PUBLIC_KEY_LENGTH_MIN) {
|
|
1067
|
+
throw new Error(
|
|
1068
|
+
`Error fetching FHE publicKey; got shorter than expected key length: ${pk_data.length}. Expected length >= ${PUBLIC_KEY_LENGTH_MIN}`
|
|
1069
|
+
);
|
|
1245
1070
|
}
|
|
1246
|
-
return items.map((item, index) => ({
|
|
1247
|
-
...item,
|
|
1248
|
-
ctHash: ctHashes[index]
|
|
1249
|
-
}));
|
|
1250
|
-
}
|
|
1251
|
-
async function insertCtHashes(items, walletClient) {
|
|
1252
|
-
const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))];
|
|
1253
1071
|
try {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1072
|
+
tfhePublicKeyDeserializer(pk_data);
|
|
1073
|
+
} catch (err) {
|
|
1074
|
+
throw new Error(`Error serializing FHE publicKey; ${err}`);
|
|
1075
|
+
}
|
|
1076
|
+
keysStorage?.setFheKey(chainId, securityZone, pk_data);
|
|
1077
|
+
return [pk_data, true];
|
|
1078
|
+
};
|
|
1079
|
+
var fetchCrs = async (coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage) => {
|
|
1080
|
+
const storedKey = keysStorage?.getCrs(chainId);
|
|
1081
|
+
const [storedKeyValid] = checkKeyValidity(storedKey, compactPkeCrsDeserializer);
|
|
1082
|
+
if (storedKeyValid)
|
|
1083
|
+
return [storedKey, false];
|
|
1084
|
+
let crs_data = void 0;
|
|
1085
|
+
try {
|
|
1086
|
+
const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
|
|
1087
|
+
method: "POST",
|
|
1088
|
+
headers: {
|
|
1089
|
+
"Content-Type": "application/json"
|
|
1090
|
+
},
|
|
1091
|
+
body: JSON.stringify({ securityZone })
|
|
1262
1092
|
});
|
|
1093
|
+
const json = await crs_res.json();
|
|
1094
|
+
crs_data = json.crs;
|
|
1095
|
+
} catch (err) {
|
|
1096
|
+
throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
|
|
1097
|
+
}
|
|
1098
|
+
if (crs_data == null || typeof crs_data !== "string") {
|
|
1099
|
+
throw new Error(`Error fetching CRS; invalid: missing or not a string`);
|
|
1100
|
+
}
|
|
1101
|
+
try {
|
|
1102
|
+
compactPkeCrsDeserializer(crs_data);
|
|
1263
1103
|
} catch (err) {
|
|
1104
|
+
console.error(`Error serializing CRS ${err}`);
|
|
1105
|
+
throw new Error(`Error serializing CRS; ${err}`);
|
|
1106
|
+
}
|
|
1107
|
+
keysStorage?.setCrs(chainId, crs_data);
|
|
1108
|
+
return [crs_data, true];
|
|
1109
|
+
};
|
|
1110
|
+
var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
|
|
1111
|
+
const coFheUrl = getCoFheUrlOrThrow(config, chainId);
|
|
1112
|
+
return await Promise.all([
|
|
1113
|
+
fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage),
|
|
1114
|
+
fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage)
|
|
1115
|
+
]);
|
|
1116
|
+
};
|
|
1117
|
+
var BaseBuilder = class {
|
|
1118
|
+
config;
|
|
1119
|
+
publicClient;
|
|
1120
|
+
walletClient;
|
|
1121
|
+
chainId;
|
|
1122
|
+
account;
|
|
1123
|
+
constructor(params) {
|
|
1124
|
+
if (!params.config) {
|
|
1125
|
+
throw new CofhesdkError({
|
|
1126
|
+
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
1127
|
+
message: "Builder config is undefined",
|
|
1128
|
+
hint: "Ensure client has been created with a config.",
|
|
1129
|
+
context: {
|
|
1130
|
+
config: params.config
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
this.config = params.config;
|
|
1135
|
+
this.publicClient = params.publicClient;
|
|
1136
|
+
this.walletClient = params.walletClient;
|
|
1137
|
+
this.chainId = params.chainId;
|
|
1138
|
+
this.account = params.account;
|
|
1139
|
+
params.requireConnected?.();
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Asserts that this.chainId is populated
|
|
1143
|
+
* @throws {CofhesdkError} If chainId is not set
|
|
1144
|
+
*/
|
|
1145
|
+
assertChainId() {
|
|
1146
|
+
if (this.chainId)
|
|
1147
|
+
return;
|
|
1264
1148
|
throw new CofhesdkError({
|
|
1265
|
-
code: "
|
|
1266
|
-
message:
|
|
1267
|
-
|
|
1149
|
+
code: "CHAIN_ID_UNINITIALIZED" /* ChainIdUninitialized */,
|
|
1150
|
+
message: "Chain ID is not set",
|
|
1151
|
+
hint: "Ensure client.connect() has been called and awaited, or use setChainId(...) to set the chainId explicitly.",
|
|
1268
1152
|
context: {
|
|
1269
|
-
|
|
1270
|
-
walletClient,
|
|
1271
|
-
insertPackedCtHashesArgs
|
|
1153
|
+
chainId: this.chainId
|
|
1272
1154
|
}
|
|
1273
1155
|
});
|
|
1274
1156
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
transport: http(),
|
|
1283
|
-
account: privateKeyToAccount(MocksEncryptedInputSignerPkey)
|
|
1284
|
-
});
|
|
1285
|
-
} catch (err) {
|
|
1157
|
+
/**
|
|
1158
|
+
* Asserts that this.account is populated
|
|
1159
|
+
* @throws {CofhesdkError} If account is not set
|
|
1160
|
+
*/
|
|
1161
|
+
assertAccount() {
|
|
1162
|
+
if (this.account)
|
|
1163
|
+
return;
|
|
1286
1164
|
throw new CofhesdkError({
|
|
1287
|
-
code: "
|
|
1288
|
-
message:
|
|
1289
|
-
|
|
1165
|
+
code: "ACCOUNT_UNINITIALIZED" /* AccountUninitialized */,
|
|
1166
|
+
message: "Account is not set",
|
|
1167
|
+
hint: "Ensure client.connect() has been called and awaited, or use setAccount(...) to set the account explicitly.",
|
|
1290
1168
|
context: {
|
|
1291
|
-
|
|
1169
|
+
account: this.account
|
|
1292
1170
|
}
|
|
1293
1171
|
});
|
|
1294
1172
|
}
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
account: encInputSignerClient.account
|
|
1303
|
-
});
|
|
1304
|
-
signatures.push(signature);
|
|
1305
|
-
}
|
|
1306
|
-
} catch (err) {
|
|
1173
|
+
/**
|
|
1174
|
+
* Asserts that this.publicClient is populated
|
|
1175
|
+
* @throws {CofhesdkError} If publicClient is not set
|
|
1176
|
+
*/
|
|
1177
|
+
assertPublicClient() {
|
|
1178
|
+
if (this.publicClient)
|
|
1179
|
+
return;
|
|
1307
1180
|
throw new CofhesdkError({
|
|
1308
|
-
code: "
|
|
1309
|
-
message:
|
|
1310
|
-
|
|
1311
|
-
context: {
|
|
1312
|
-
|
|
1313
|
-
securityZone
|
|
1181
|
+
code: "MISSING_PUBLIC_CLIENT" /* MissingPublicClient */,
|
|
1182
|
+
message: "Public client not found",
|
|
1183
|
+
hint: "Ensure client.connect() has been called with a publicClient.",
|
|
1184
|
+
context: {
|
|
1185
|
+
publicClient: this.publicClient
|
|
1314
1186
|
}
|
|
1315
1187
|
});
|
|
1316
1188
|
}
|
|
1317
|
-
|
|
1189
|
+
/**
|
|
1190
|
+
* Asserts that this.walletClient is populated
|
|
1191
|
+
* @throws {CofhesdkError} If walletClient is not set
|
|
1192
|
+
*/
|
|
1193
|
+
assertWalletClient() {
|
|
1194
|
+
if (this.walletClient)
|
|
1195
|
+
return;
|
|
1318
1196
|
throw new CofhesdkError({
|
|
1319
|
-
code: "
|
|
1320
|
-
message:
|
|
1197
|
+
code: "MISSING_WALLET_CLIENT" /* MissingWalletClient */,
|
|
1198
|
+
message: "Wallet client not found",
|
|
1199
|
+
hint: "Ensure client.connect() has been called with a walletClient.",
|
|
1321
1200
|
context: {
|
|
1322
|
-
|
|
1323
|
-
securityZone
|
|
1201
|
+
walletClient: this.walletClient
|
|
1324
1202
|
}
|
|
1325
1203
|
});
|
|
1326
1204
|
}
|
|
1327
|
-
|
|
1328
|
-
}
|
|
1329
|
-
async function cofheMocksZkVerifySign(items, account, securityZone, publicClient, walletClient, zkvWalletClient) {
|
|
1330
|
-
const _walletClient = zkvWalletClient ?? walletClient;
|
|
1331
|
-
const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
|
|
1332
|
-
await insertCtHashes(encryptableItems, _walletClient);
|
|
1333
|
-
const signatures = await createProofSignatures(encryptableItems, securityZone);
|
|
1334
|
-
return encryptableItems.map((item, index) => ({
|
|
1335
|
-
ct_hash: item.ctHash.toString(),
|
|
1336
|
-
signature: signatures[index]
|
|
1337
|
-
}));
|
|
1338
|
-
}
|
|
1339
|
-
function createKeysStore(storage) {
|
|
1340
|
-
const keysStore = storage ? createStore()(
|
|
1341
|
-
persist(
|
|
1342
|
-
() => ({
|
|
1343
|
-
fhe: {},
|
|
1344
|
-
crs: {}
|
|
1345
|
-
}),
|
|
1346
|
-
{
|
|
1347
|
-
name: "cofhesdk-keys",
|
|
1348
|
-
storage: createJSONStorage(() => storage),
|
|
1349
|
-
merge: (persistedState, currentState) => {
|
|
1350
|
-
const persisted = persistedState;
|
|
1351
|
-
const current = currentState;
|
|
1352
|
-
const mergedFhe = { ...persisted.fhe };
|
|
1353
|
-
const allChainIds = /* @__PURE__ */ new Set([...Object.keys(current.fhe), ...Object.keys(persisted.fhe)]);
|
|
1354
|
-
for (const chainId of allChainIds) {
|
|
1355
|
-
const persistedZones = persisted.fhe[chainId] || {};
|
|
1356
|
-
const currentZones = current.fhe[chainId] || {};
|
|
1357
|
-
mergedFhe[chainId] = { ...persistedZones, ...currentZones };
|
|
1358
|
-
}
|
|
1359
|
-
const mergedCrs = { ...persisted.crs, ...current.crs };
|
|
1360
|
-
return {
|
|
1361
|
-
fhe: mergedFhe,
|
|
1362
|
-
crs: mergedCrs
|
|
1363
|
-
};
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
)
|
|
1367
|
-
) : createStore()(() => ({
|
|
1368
|
-
fhe: {},
|
|
1369
|
-
crs: {}
|
|
1370
|
-
}));
|
|
1371
|
-
const getFheKey = (chainId, securityZone = 0) => {
|
|
1372
|
-
if (chainId == null || securityZone == null)
|
|
1373
|
-
return void 0;
|
|
1374
|
-
const stored = keysStore.getState().fhe[chainId]?.[securityZone];
|
|
1375
|
-
return stored;
|
|
1376
|
-
};
|
|
1377
|
-
const getCrs = (chainId) => {
|
|
1378
|
-
if (chainId == null)
|
|
1379
|
-
return void 0;
|
|
1380
|
-
const stored = keysStore.getState().crs[chainId];
|
|
1381
|
-
return stored;
|
|
1382
|
-
};
|
|
1383
|
-
const setFheKey = (chainId, securityZone, key) => {
|
|
1384
|
-
keysStore.setState(
|
|
1385
|
-
produce((state) => {
|
|
1386
|
-
if (state.fhe[chainId] == null)
|
|
1387
|
-
state.fhe[chainId] = {};
|
|
1388
|
-
state.fhe[chainId][securityZone] = key;
|
|
1389
|
-
})
|
|
1390
|
-
);
|
|
1391
|
-
};
|
|
1392
|
-
const setCrs = (chainId, crs) => {
|
|
1393
|
-
keysStore.setState(
|
|
1394
|
-
produce((state) => {
|
|
1395
|
-
state.crs[chainId] = crs;
|
|
1396
|
-
})
|
|
1397
|
-
);
|
|
1398
|
-
};
|
|
1399
|
-
const clearKeysStorage = async () => {
|
|
1400
|
-
if (storage) {
|
|
1401
|
-
await storage.removeItem("cofhesdk-keys");
|
|
1402
|
-
}
|
|
1403
|
-
};
|
|
1404
|
-
const rehydrateKeysStore = async () => {
|
|
1405
|
-
if ("persist" in keysStore) {
|
|
1406
|
-
if (keysStore.persist.hasHydrated())
|
|
1407
|
-
return;
|
|
1408
|
-
await keysStore.persist.rehydrate();
|
|
1409
|
-
}
|
|
1410
|
-
};
|
|
1411
|
-
return {
|
|
1412
|
-
store: keysStore,
|
|
1413
|
-
getFheKey,
|
|
1414
|
-
getCrs,
|
|
1415
|
-
setFheKey,
|
|
1416
|
-
setCrs,
|
|
1417
|
-
clearKeysStorage,
|
|
1418
|
-
rehydrateKeysStore
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1205
|
+
};
|
|
1421
1206
|
|
|
1422
1207
|
// core/encrypt/encryptInputsBuilder.ts
|
|
1423
1208
|
var EncryptInputsBuilder = class extends BaseBuilder {
|
|
@@ -1429,7 +1214,10 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1429
1214
|
compactPkeCrsDeserializer;
|
|
1430
1215
|
zkBuilderAndCrsGenerator;
|
|
1431
1216
|
initTfhe;
|
|
1217
|
+
zkProveWorkerFn;
|
|
1432
1218
|
keysStorage;
|
|
1219
|
+
// Worker configuration (from config, overrideable)
|
|
1220
|
+
useWorker;
|
|
1433
1221
|
stepTimestamps = {
|
|
1434
1222
|
["initTfhe" /* InitTfhe */]: 0,
|
|
1435
1223
|
["fetchKeys" /* FetchKeys */]: 0,
|
|
@@ -1449,11 +1237,43 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1449
1237
|
this.inputItems = params.inputs;
|
|
1450
1238
|
this.securityZone = params.securityZone ?? 0;
|
|
1451
1239
|
this.zkvWalletClient = params.zkvWalletClient;
|
|
1240
|
+
if (!params.tfhePublicKeyDeserializer) {
|
|
1241
|
+
throw new CofhesdkError({
|
|
1242
|
+
code: "MISSING_TFHE_PUBLIC_KEY_DESERIALIZER" /* MissingTfhePublicKeyDeserializer */,
|
|
1243
|
+
message: "EncryptInputsBuilder tfhePublicKeyDeserializer is undefined",
|
|
1244
|
+
hint: "Ensure client has been created with a tfhePublicKeyDeserializer.",
|
|
1245
|
+
context: {
|
|
1246
|
+
tfhePublicKeyDeserializer: params.tfhePublicKeyDeserializer
|
|
1247
|
+
}
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1452
1250
|
this.tfhePublicKeyDeserializer = params.tfhePublicKeyDeserializer;
|
|
1251
|
+
if (!params.compactPkeCrsDeserializer) {
|
|
1252
|
+
throw new CofhesdkError({
|
|
1253
|
+
code: "MISSING_COMPACT_PKE_CRS_DESERIALIZER" /* MissingCompactPkeCrsDeserializer */,
|
|
1254
|
+
message: "EncryptInputsBuilder compactPkeCrsDeserializer is undefined",
|
|
1255
|
+
hint: "Ensure client has been created with a compactPkeCrsDeserializer.",
|
|
1256
|
+
context: {
|
|
1257
|
+
compactPkeCrsDeserializer: params.compactPkeCrsDeserializer
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1453
1261
|
this.compactPkeCrsDeserializer = params.compactPkeCrsDeserializer;
|
|
1262
|
+
if (!params.zkBuilderAndCrsGenerator) {
|
|
1263
|
+
throw new CofhesdkError({
|
|
1264
|
+
code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
|
|
1265
|
+
message: "EncryptInputsBuilder zkBuilderAndCrsGenerator is undefined",
|
|
1266
|
+
hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
|
|
1267
|
+
context: {
|
|
1268
|
+
zkBuilderAndCrsGenerator: params.zkBuilderAndCrsGenerator
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1454
1272
|
this.zkBuilderAndCrsGenerator = params.zkBuilderAndCrsGenerator;
|
|
1455
1273
|
this.initTfhe = params.initTfhe;
|
|
1274
|
+
this.zkProveWorkerFn = params.zkProveWorkerFn;
|
|
1456
1275
|
this.keysStorage = params.keysStorage;
|
|
1276
|
+
this.useWorker = params.config?.useWorkers ?? true;
|
|
1457
1277
|
}
|
|
1458
1278
|
/**
|
|
1459
1279
|
* @param account - Account that will create the tx using the encrypted inputs.
|
|
@@ -1498,611 +1318,1022 @@ var EncryptInputsBuilder = class extends BaseBuilder {
|
|
|
1498
1318
|
return this.chainId;
|
|
1499
1319
|
}
|
|
1500
1320
|
/**
|
|
1501
|
-
* @param securityZone - Security zone to encrypt the inputs for.
|
|
1502
|
-
*
|
|
1503
|
-
* If not provided, the default securityZone 0 will be used.
|
|
1504
|
-
*
|
|
1505
|
-
* Example:
|
|
1506
|
-
* ```typescript
|
|
1507
|
-
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1508
|
-
* .setSecurityZone(1)
|
|
1509
|
-
* .encrypt();
|
|
1510
|
-
* ```
|
|
1321
|
+
* @param securityZone - Security zone to encrypt the inputs for.
|
|
1322
|
+
*
|
|
1323
|
+
* If not provided, the default securityZone 0 will be used.
|
|
1324
|
+
*
|
|
1325
|
+
* Example:
|
|
1326
|
+
* ```typescript
|
|
1327
|
+
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1328
|
+
* .setSecurityZone(1)
|
|
1329
|
+
* .encrypt();
|
|
1330
|
+
* ```
|
|
1331
|
+
*
|
|
1332
|
+
* @returns The chainable EncryptInputsBuilder instance.
|
|
1333
|
+
*/
|
|
1334
|
+
setSecurityZone(securityZone) {
|
|
1335
|
+
this.securityZone = securityZone;
|
|
1336
|
+
return this;
|
|
1337
|
+
}
|
|
1338
|
+
getSecurityZone() {
|
|
1339
|
+
return this.securityZone;
|
|
1340
|
+
}
|
|
1341
|
+
/**
|
|
1342
|
+
* @param useWorker - Whether to use Web Workers for ZK proof generation.
|
|
1343
|
+
*
|
|
1344
|
+
* Overrides the config-level useWorkers setting for this specific encryption.
|
|
1345
|
+
*
|
|
1346
|
+
* Example:
|
|
1347
|
+
* ```typescript
|
|
1348
|
+
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1349
|
+
* .setUseWorker(false)
|
|
1350
|
+
* .encrypt();
|
|
1351
|
+
* ```
|
|
1352
|
+
*
|
|
1353
|
+
* @returns The chainable EncryptInputsBuilder instance.
|
|
1354
|
+
*/
|
|
1355
|
+
setUseWorker(useWorker) {
|
|
1356
|
+
this.useWorker = useWorker;
|
|
1357
|
+
return this;
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Gets the current worker configuration.
|
|
1361
|
+
*
|
|
1362
|
+
* @returns Whether Web Workers are enabled for this encryption.
|
|
1363
|
+
*
|
|
1364
|
+
* Example:
|
|
1365
|
+
* ```typescript
|
|
1366
|
+
* const builder = encryptInputs([Encryptable.uint128(10n)]);
|
|
1367
|
+
* console.log(builder.getUseWorker()); // true (from config)
|
|
1368
|
+
* builder.setUseWorker(false);
|
|
1369
|
+
* console.log(builder.getUseWorker()); // false (overridden)
|
|
1370
|
+
* ```
|
|
1371
|
+
*/
|
|
1372
|
+
getUseWorker() {
|
|
1373
|
+
return this.useWorker;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* @param callback - Function to be called with the encryption step.
|
|
1377
|
+
*
|
|
1378
|
+
* Useful for debugging and tracking the progress of the encryption process.
|
|
1379
|
+
* Useful for a UI element that shows the progress of the encryption process.
|
|
1380
|
+
*
|
|
1381
|
+
* Example:
|
|
1382
|
+
* ```typescript
|
|
1383
|
+
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1384
|
+
* .setStepCallback((step: EncryptStep) => console.log(step))
|
|
1385
|
+
* .encrypt();
|
|
1386
|
+
* ```
|
|
1387
|
+
*
|
|
1388
|
+
* @returns The EncryptInputsBuilder instance.
|
|
1389
|
+
*/
|
|
1390
|
+
setStepCallback(callback) {
|
|
1391
|
+
this.stepCallback = callback;
|
|
1392
|
+
return this;
|
|
1393
|
+
}
|
|
1394
|
+
getStepCallback() {
|
|
1395
|
+
return this.stepCallback;
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* Fires the step callback if set
|
|
1399
|
+
*/
|
|
1400
|
+
fireStepStart(step, context = {}) {
|
|
1401
|
+
if (!this.stepCallback)
|
|
1402
|
+
return;
|
|
1403
|
+
this.stepTimestamps[step] = Date.now();
|
|
1404
|
+
this.stepCallback(step, { ...context, isStart: true, isEnd: false, duration: 0 });
|
|
1405
|
+
}
|
|
1406
|
+
fireStepEnd(step, context = {}) {
|
|
1407
|
+
if (!this.stepCallback)
|
|
1408
|
+
return;
|
|
1409
|
+
const duration = Date.now() - this.stepTimestamps[step];
|
|
1410
|
+
this.stepCallback(step, { ...context, isStart: false, isEnd: true, duration });
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* zkVerifierUrl is included in the chains exported from cofhesdk/chains for use in CofhesdkConfig.supportedChains
|
|
1414
|
+
* Users should generally not set this manually.
|
|
1415
|
+
*/
|
|
1416
|
+
async getZkVerifierUrl() {
|
|
1417
|
+
this.assertChainId();
|
|
1418
|
+
return getZkVerifierUrlOrThrow(this.config, this.chainId);
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* initTfhe is a platform-specific dependency injected into core/createCofhesdkClientBase by web/createCofhesdkClient and node/createCofhesdkClient
|
|
1422
|
+
* web/ uses zama "tfhe"
|
|
1423
|
+
* node/ uses zama "node-tfhe"
|
|
1424
|
+
* Users should not set this manually.
|
|
1425
|
+
*/
|
|
1426
|
+
async initTfheOrThrow() {
|
|
1427
|
+
if (!this.initTfhe)
|
|
1428
|
+
return false;
|
|
1429
|
+
try {
|
|
1430
|
+
return await this.initTfhe();
|
|
1431
|
+
} catch (error) {
|
|
1432
|
+
throw CofhesdkError.fromError(error, {
|
|
1433
|
+
code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
|
|
1434
|
+
message: `Failed to initialize TFHE`,
|
|
1435
|
+
context: {
|
|
1436
|
+
initTfhe: this.initTfhe
|
|
1437
|
+
}
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
/**
|
|
1442
|
+
* Fetches the FHE key and CRS from the CoFHE API
|
|
1443
|
+
* If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
|
|
1444
|
+
*/
|
|
1445
|
+
async fetchFheKeyAndCrs() {
|
|
1446
|
+
this.assertChainId();
|
|
1447
|
+
const securityZone = this.getSecurityZone();
|
|
1448
|
+
try {
|
|
1449
|
+
await this.keysStorage?.rehydrateKeysStore();
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
throw CofhesdkError.fromError(error, {
|
|
1452
|
+
code: "REHYDRATE_KEYS_STORE_FAILED" /* RehydrateKeysStoreFailed */,
|
|
1453
|
+
message: `Failed to rehydrate keys store`,
|
|
1454
|
+
context: {
|
|
1455
|
+
keysStorage: this.keysStorage
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
let fheKey;
|
|
1460
|
+
let fheKeyFetchedFromCoFHE = false;
|
|
1461
|
+
let crs;
|
|
1462
|
+
let crsFetchedFromCoFHE = false;
|
|
1463
|
+
try {
|
|
1464
|
+
[[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
|
|
1465
|
+
this.config,
|
|
1466
|
+
this.chainId,
|
|
1467
|
+
securityZone,
|
|
1468
|
+
this.tfhePublicKeyDeserializer,
|
|
1469
|
+
this.compactPkeCrsDeserializer,
|
|
1470
|
+
this.keysStorage
|
|
1471
|
+
);
|
|
1472
|
+
} catch (error) {
|
|
1473
|
+
throw CofhesdkError.fromError(error, {
|
|
1474
|
+
code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
|
|
1475
|
+
message: `Failed to fetch FHE key and CRS`,
|
|
1476
|
+
context: {
|
|
1477
|
+
config: this.config,
|
|
1478
|
+
chainId: this.chainId,
|
|
1479
|
+
securityZone,
|
|
1480
|
+
compactPkeCrsDeserializer: this.compactPkeCrsDeserializer,
|
|
1481
|
+
tfhePublicKeyDeserializer: this.tfhePublicKeyDeserializer
|
|
1482
|
+
}
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
if (!fheKey) {
|
|
1486
|
+
throw new CofhesdkError({
|
|
1487
|
+
code: "MISSING_FHE_KEY" /* MissingFheKey */,
|
|
1488
|
+
message: `FHE key not found`,
|
|
1489
|
+
context: {
|
|
1490
|
+
chainId: this.chainId,
|
|
1491
|
+
securityZone
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
}
|
|
1495
|
+
if (!crs) {
|
|
1496
|
+
throw new CofhesdkError({
|
|
1497
|
+
code: "MISSING_CRS" /* MissingCrs */,
|
|
1498
|
+
message: `CRS not found for chainId <${this.chainId}>`,
|
|
1499
|
+
context: {
|
|
1500
|
+
chainId: this.chainId
|
|
1501
|
+
}
|
|
1502
|
+
});
|
|
1503
|
+
}
|
|
1504
|
+
return { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE };
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* @dev Encrypt against the cofheMocks instead of CoFHE
|
|
1511
1508
|
*
|
|
1512
|
-
*
|
|
1509
|
+
* In the cofheMocks, the MockZkVerifier contract is deployed on hardhat to a fixed address, this contract handles mocking the zk verifying.
|
|
1510
|
+
* cofheMocksInsertPackedHashes - stores the ctHashes and their plaintext values for on-chain mocking of FHE operations.
|
|
1511
|
+
* cofheMocksZkCreateProofSignatures - creates signatures to be included in the encrypted inputs. The signers address is known and verified in the mock contracts.
|
|
1513
1512
|
*/
|
|
1514
|
-
|
|
1515
|
-
this.
|
|
1516
|
-
|
|
1513
|
+
async mocksEncrypt() {
|
|
1514
|
+
this.assertAccount();
|
|
1515
|
+
this.assertPublicClient();
|
|
1516
|
+
this.assertWalletClient();
|
|
1517
|
+
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1518
|
+
await sleep(100);
|
|
1519
|
+
this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
|
|
1520
|
+
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1521
|
+
await sleep(100);
|
|
1522
|
+
this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE: false, crsFetchedFromCoFHE: false });
|
|
1523
|
+
this.fireStepStart("pack" /* Pack */);
|
|
1524
|
+
await cofheMocksCheckEncryptableBits(this.inputItems);
|
|
1525
|
+
await sleep(100);
|
|
1526
|
+
this.fireStepEnd("pack" /* Pack */);
|
|
1527
|
+
this.fireStepStart("prove" /* Prove */);
|
|
1528
|
+
await sleep(500);
|
|
1529
|
+
this.fireStepEnd("prove" /* Prove */);
|
|
1530
|
+
this.fireStepStart("verify" /* Verify */);
|
|
1531
|
+
await sleep(500);
|
|
1532
|
+
const signedResults = await cofheMocksZkVerifySign(
|
|
1533
|
+
this.inputItems,
|
|
1534
|
+
this.account,
|
|
1535
|
+
this.securityZone,
|
|
1536
|
+
this.publicClient,
|
|
1537
|
+
this.walletClient,
|
|
1538
|
+
this.zkvWalletClient
|
|
1539
|
+
);
|
|
1540
|
+
const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
|
|
1541
|
+
ctHash: BigInt(ct_hash),
|
|
1542
|
+
securityZone: this.securityZone,
|
|
1543
|
+
utype: this.inputItems[index].utype,
|
|
1544
|
+
signature
|
|
1545
|
+
}));
|
|
1546
|
+
this.fireStepEnd("verify" /* Verify */);
|
|
1547
|
+
return encryptedInputs;
|
|
1517
1548
|
}
|
|
1518
|
-
|
|
1519
|
-
|
|
1549
|
+
/**
|
|
1550
|
+
* In the production context, perform a true encryption with the CoFHE coprocessor.
|
|
1551
|
+
*/
|
|
1552
|
+
async productionEncrypt() {
|
|
1553
|
+
this.assertAccount();
|
|
1554
|
+
this.assertChainId();
|
|
1555
|
+
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1556
|
+
const tfheInitializationExecuted = await this.initTfheOrThrow();
|
|
1557
|
+
this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
|
|
1558
|
+
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1559
|
+
const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
|
|
1560
|
+
let { zkBuilder, zkCrs } = this.zkBuilderAndCrsGenerator(fheKey, crs);
|
|
1561
|
+
this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
|
|
1562
|
+
this.fireStepStart("pack" /* Pack */);
|
|
1563
|
+
zkBuilder = zkPack(this.inputItems, zkBuilder);
|
|
1564
|
+
this.fireStepEnd("pack" /* Pack */);
|
|
1565
|
+
this.fireStepStart("prove" /* Prove */);
|
|
1566
|
+
const metadata = constructZkPoKMetadata(this.account, this.securityZone, this.chainId);
|
|
1567
|
+
let proof = null;
|
|
1568
|
+
let usedWorker = false;
|
|
1569
|
+
let workerFailedError;
|
|
1570
|
+
if (this.useWorker && this.zkProveWorkerFn) {
|
|
1571
|
+
try {
|
|
1572
|
+
proof = await zkProveWithWorker(this.zkProveWorkerFn, fheKey, crs, this.inputItems, metadata);
|
|
1573
|
+
usedWorker = true;
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
workerFailedError = error instanceof Error ? error.message : String(error);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
if (proof == null) {
|
|
1579
|
+
proof = await zkProve(zkBuilder, zkCrs, metadata);
|
|
1580
|
+
usedWorker = false;
|
|
1581
|
+
}
|
|
1582
|
+
this.fireStepEnd("prove" /* Prove */, {
|
|
1583
|
+
useWorker: this.useWorker,
|
|
1584
|
+
usedWorker,
|
|
1585
|
+
workerFailedError
|
|
1586
|
+
});
|
|
1587
|
+
this.fireStepStart("verify" /* Verify */);
|
|
1588
|
+
const zkVerifierUrl = await this.getZkVerifierUrl();
|
|
1589
|
+
const verifyResults = await zkVerify(zkVerifierUrl, proof, this.account, this.securityZone, this.chainId);
|
|
1590
|
+
const encryptedInputs = verifyResults.map(
|
|
1591
|
+
({ ct_hash, signature }, index) => ({
|
|
1592
|
+
ctHash: BigInt(ct_hash),
|
|
1593
|
+
securityZone: this.securityZone,
|
|
1594
|
+
utype: this.inputItems[index].utype,
|
|
1595
|
+
signature
|
|
1596
|
+
})
|
|
1597
|
+
);
|
|
1598
|
+
this.fireStepEnd("verify" /* Verify */);
|
|
1599
|
+
return encryptedInputs;
|
|
1520
1600
|
}
|
|
1521
1601
|
/**
|
|
1522
|
-
*
|
|
1602
|
+
* Final step of the encryption process. MUST BE CALLED LAST IN THE CHAIN.
|
|
1523
1603
|
*
|
|
1524
|
-
*
|
|
1525
|
-
*
|
|
1604
|
+
* This will:
|
|
1605
|
+
* - Pack the encryptable items into a zk proof
|
|
1606
|
+
* - Prove the zk proof
|
|
1607
|
+
* - Verify the zk proof with CoFHE
|
|
1608
|
+
* - Package and return the encrypted inputs
|
|
1526
1609
|
*
|
|
1527
1610
|
* Example:
|
|
1528
1611
|
* ```typescript
|
|
1529
1612
|
* const encrypted = await encryptInputs([Encryptable.uint128(10n)])
|
|
1530
|
-
* .
|
|
1531
|
-
* .
|
|
1613
|
+
* .setAccount('0x123...890') // optional
|
|
1614
|
+
* .setChainId(11155111) // optional
|
|
1615
|
+
* .encrypt(); // execute
|
|
1532
1616
|
* ```
|
|
1533
1617
|
*
|
|
1534
|
-
* @returns The
|
|
1618
|
+
* @returns The encrypted inputs.
|
|
1535
1619
|
*/
|
|
1536
|
-
|
|
1537
|
-
this.
|
|
1538
|
-
|
|
1620
|
+
async encrypt() {
|
|
1621
|
+
if (this.chainId === hardhat.id)
|
|
1622
|
+
return this.mocksEncrypt();
|
|
1623
|
+
return this.productionEncrypt();
|
|
1624
|
+
}
|
|
1625
|
+
};
|
|
1626
|
+
var storeActivePermit = async (permit, publicClient, walletClient) => {
|
|
1627
|
+
const chainId = await publicClient.getChainId();
|
|
1628
|
+
const account = walletClient.account.address;
|
|
1629
|
+
permitStore.setPermit(chainId, account, permit);
|
|
1630
|
+
permitStore.setActivePermitHash(chainId, account, PermitUtils.getHash(permit));
|
|
1631
|
+
};
|
|
1632
|
+
var createPermitWithSign = async (options, publicClient, walletClient, permitMethod) => {
|
|
1633
|
+
const permit = await permitMethod(options, publicClient, walletClient);
|
|
1634
|
+
await storeActivePermit(permit, publicClient, walletClient);
|
|
1635
|
+
return permit;
|
|
1636
|
+
};
|
|
1637
|
+
var createSelf = async (options, publicClient, walletClient) => {
|
|
1638
|
+
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSelfAndSign);
|
|
1639
|
+
};
|
|
1640
|
+
var createSharing = async (options, publicClient, walletClient) => {
|
|
1641
|
+
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.createSharingAndSign);
|
|
1642
|
+
};
|
|
1643
|
+
var importShared = async (options, publicClient, walletClient) => {
|
|
1644
|
+
return createPermitWithSign(options, publicClient, walletClient, PermitUtils.importSharedAndSign);
|
|
1645
|
+
};
|
|
1646
|
+
var getHash = (permit) => {
|
|
1647
|
+
return PermitUtils.getHash(permit);
|
|
1648
|
+
};
|
|
1649
|
+
var serialize = (permit) => {
|
|
1650
|
+
return PermitUtils.serialize(permit);
|
|
1651
|
+
};
|
|
1652
|
+
var deserialize = (serialized) => {
|
|
1653
|
+
return PermitUtils.deserialize(serialized);
|
|
1654
|
+
};
|
|
1655
|
+
var getPermit = async (chainId, account, hash) => {
|
|
1656
|
+
return permitStore.getPermit(chainId, account, hash);
|
|
1657
|
+
};
|
|
1658
|
+
var getPermits = async (chainId, account) => {
|
|
1659
|
+
return permitStore.getPermits(chainId, account);
|
|
1660
|
+
};
|
|
1661
|
+
var getActivePermit = async (chainId, account) => {
|
|
1662
|
+
return permitStore.getActivePermit(chainId, account);
|
|
1663
|
+
};
|
|
1664
|
+
var getActivePermitHash = (chainId, account) => {
|
|
1665
|
+
return permitStore.getActivePermitHash(chainId, account);
|
|
1666
|
+
};
|
|
1667
|
+
var selectActivePermit = (chainId, account, hash) => {
|
|
1668
|
+
permitStore.setActivePermitHash(chainId, account, hash);
|
|
1669
|
+
};
|
|
1670
|
+
var getOrCreateSelfPermit = async (publicClient, walletClient, chainId, account, options) => {
|
|
1671
|
+
const _chainId = chainId ?? await publicClient.getChainId();
|
|
1672
|
+
const _account = account ?? walletClient.account.address;
|
|
1673
|
+
const activePermit = await getActivePermit(_chainId, _account);
|
|
1674
|
+
if (activePermit && activePermit.type === "self") {
|
|
1675
|
+
return activePermit;
|
|
1676
|
+
}
|
|
1677
|
+
return createSelf(options ?? { issuer: _account, name: "Autogenerated Self Permit" }, publicClient, walletClient);
|
|
1678
|
+
};
|
|
1679
|
+
var getOrCreateSharingPermit = async (publicClient, walletClient, options, chainId, account) => {
|
|
1680
|
+
const _chainId = chainId ?? await publicClient.getChainId();
|
|
1681
|
+
const _account = account ?? walletClient.account.address;
|
|
1682
|
+
const activePermit = await getActivePermit(_chainId, _account);
|
|
1683
|
+
if (activePermit && activePermit.type === "sharing") {
|
|
1684
|
+
return activePermit;
|
|
1685
|
+
}
|
|
1686
|
+
return createSharing(options, publicClient, walletClient);
|
|
1687
|
+
};
|
|
1688
|
+
var removePermit = async (chainId, account, hash, force) => permitStore.removePermit(chainId, account, hash, force);
|
|
1689
|
+
var removeActivePermit = async (chainId, account) => permitStore.removeActivePermitHash(chainId, account);
|
|
1690
|
+
var permits = {
|
|
1691
|
+
getSnapshot: permitStore.store.getState,
|
|
1692
|
+
subscribe: permitStore.store.subscribe,
|
|
1693
|
+
createSelf,
|
|
1694
|
+
createSharing,
|
|
1695
|
+
importShared,
|
|
1696
|
+
getOrCreateSelfPermit,
|
|
1697
|
+
getOrCreateSharingPermit,
|
|
1698
|
+
getHash,
|
|
1699
|
+
serialize,
|
|
1700
|
+
deserialize,
|
|
1701
|
+
getPermit,
|
|
1702
|
+
getPermits,
|
|
1703
|
+
getActivePermit,
|
|
1704
|
+
getActivePermitHash,
|
|
1705
|
+
removePermit,
|
|
1706
|
+
selectActivePermit,
|
|
1707
|
+
removeActivePermit
|
|
1708
|
+
};
|
|
1709
|
+
function uint160ToAddress(uint160) {
|
|
1710
|
+
const hexStr = uint160.toString(16).padStart(40, "0");
|
|
1711
|
+
return getAddress("0x" + hexStr);
|
|
1712
|
+
}
|
|
1713
|
+
var isValidUtype = (utype) => {
|
|
1714
|
+
return utype === 0 /* Bool */ || utype === 7 /* Uint160 */ || utype == null || FheUintUTypes.includes(utype);
|
|
1715
|
+
};
|
|
1716
|
+
var convertViaUtype = (utype, value) => {
|
|
1717
|
+
if (utype === 0 /* Bool */) {
|
|
1718
|
+
return !!value;
|
|
1719
|
+
} else if (utype === 7 /* Uint160 */) {
|
|
1720
|
+
return uint160ToAddress(value);
|
|
1721
|
+
} else if (utype == null || FheUintUTypes.includes(utype)) {
|
|
1722
|
+
return value;
|
|
1723
|
+
} else {
|
|
1724
|
+
throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
|
|
1725
|
+
}
|
|
1726
|
+
};
|
|
1727
|
+
|
|
1728
|
+
// core/decrypt/MockQueryDecrypterAbi.ts
|
|
1729
|
+
var MockQueryDecrypterAbi = [
|
|
1730
|
+
{
|
|
1731
|
+
type: "function",
|
|
1732
|
+
name: "acl",
|
|
1733
|
+
inputs: [],
|
|
1734
|
+
outputs: [{ name: "", type: "address", internalType: "contract ACL" }],
|
|
1735
|
+
stateMutability: "view"
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
type: "function",
|
|
1739
|
+
name: "decodeLowLevelReversion",
|
|
1740
|
+
inputs: [{ name: "data", type: "bytes", internalType: "bytes" }],
|
|
1741
|
+
outputs: [{ name: "error", type: "string", internalType: "string" }],
|
|
1742
|
+
stateMutability: "pure"
|
|
1743
|
+
},
|
|
1744
|
+
{
|
|
1745
|
+
type: "function",
|
|
1746
|
+
name: "exists",
|
|
1747
|
+
inputs: [],
|
|
1748
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
1749
|
+
stateMutability: "pure"
|
|
1750
|
+
},
|
|
1751
|
+
{
|
|
1752
|
+
type: "function",
|
|
1753
|
+
name: "initialize",
|
|
1754
|
+
inputs: [
|
|
1755
|
+
{ name: "_taskManager", type: "address", internalType: "address" },
|
|
1756
|
+
{ name: "_acl", type: "address", internalType: "address" }
|
|
1757
|
+
],
|
|
1758
|
+
outputs: [],
|
|
1759
|
+
stateMutability: "nonpayable"
|
|
1760
|
+
},
|
|
1761
|
+
{
|
|
1762
|
+
type: "function",
|
|
1763
|
+
name: "queryDecrypt",
|
|
1764
|
+
inputs: [
|
|
1765
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
1766
|
+
{ name: "", type: "uint256", internalType: "uint256" },
|
|
1767
|
+
{
|
|
1768
|
+
name: "permission",
|
|
1769
|
+
type: "tuple",
|
|
1770
|
+
internalType: "struct Permission",
|
|
1771
|
+
components: [
|
|
1772
|
+
{ name: "issuer", type: "address", internalType: "address" },
|
|
1773
|
+
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
1774
|
+
{ name: "recipient", type: "address", internalType: "address" },
|
|
1775
|
+
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
1776
|
+
{
|
|
1777
|
+
name: "validatorContract",
|
|
1778
|
+
type: "address",
|
|
1779
|
+
internalType: "address"
|
|
1780
|
+
},
|
|
1781
|
+
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
1782
|
+
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
1783
|
+
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
1784
|
+
]
|
|
1785
|
+
}
|
|
1786
|
+
],
|
|
1787
|
+
outputs: [
|
|
1788
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
1789
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
1790
|
+
{ name: "", type: "uint256", internalType: "uint256" }
|
|
1791
|
+
],
|
|
1792
|
+
stateMutability: "view"
|
|
1793
|
+
},
|
|
1794
|
+
{
|
|
1795
|
+
type: "function",
|
|
1796
|
+
name: "querySealOutput",
|
|
1797
|
+
inputs: [
|
|
1798
|
+
{ name: "ctHash", type: "uint256", internalType: "uint256" },
|
|
1799
|
+
{ name: "", type: "uint256", internalType: "uint256" },
|
|
1800
|
+
{
|
|
1801
|
+
name: "permission",
|
|
1802
|
+
type: "tuple",
|
|
1803
|
+
internalType: "struct Permission",
|
|
1804
|
+
components: [
|
|
1805
|
+
{ name: "issuer", type: "address", internalType: "address" },
|
|
1806
|
+
{ name: "expiration", type: "uint64", internalType: "uint64" },
|
|
1807
|
+
{ name: "recipient", type: "address", internalType: "address" },
|
|
1808
|
+
{ name: "validatorId", type: "uint256", internalType: "uint256" },
|
|
1809
|
+
{
|
|
1810
|
+
name: "validatorContract",
|
|
1811
|
+
type: "address",
|
|
1812
|
+
internalType: "address"
|
|
1813
|
+
},
|
|
1814
|
+
{ name: "sealingKey", type: "bytes32", internalType: "bytes32" },
|
|
1815
|
+
{ name: "issuerSignature", type: "bytes", internalType: "bytes" },
|
|
1816
|
+
{ name: "recipientSignature", type: "bytes", internalType: "bytes" }
|
|
1817
|
+
]
|
|
1818
|
+
}
|
|
1819
|
+
],
|
|
1820
|
+
outputs: [
|
|
1821
|
+
{ name: "allowed", type: "bool", internalType: "bool" },
|
|
1822
|
+
{ name: "error", type: "string", internalType: "string" },
|
|
1823
|
+
{ name: "", type: "bytes32", internalType: "bytes32" }
|
|
1824
|
+
],
|
|
1825
|
+
stateMutability: "view"
|
|
1826
|
+
},
|
|
1827
|
+
{
|
|
1828
|
+
type: "function",
|
|
1829
|
+
name: "seal",
|
|
1830
|
+
inputs: [
|
|
1831
|
+
{ name: "input", type: "uint256", internalType: "uint256" },
|
|
1832
|
+
{ name: "key", type: "bytes32", internalType: "bytes32" }
|
|
1833
|
+
],
|
|
1834
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
1835
|
+
stateMutability: "pure"
|
|
1836
|
+
},
|
|
1837
|
+
{
|
|
1838
|
+
type: "function",
|
|
1839
|
+
name: "taskManager",
|
|
1840
|
+
inputs: [],
|
|
1841
|
+
outputs: [{ name: "", type: "address", internalType: "contract TaskManager" }],
|
|
1842
|
+
stateMutability: "view"
|
|
1843
|
+
},
|
|
1844
|
+
{
|
|
1845
|
+
type: "function",
|
|
1846
|
+
name: "unseal",
|
|
1847
|
+
inputs: [
|
|
1848
|
+
{ name: "hashed", type: "bytes32", internalType: "bytes32" },
|
|
1849
|
+
{ name: "key", type: "bytes32", internalType: "bytes32" }
|
|
1850
|
+
],
|
|
1851
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
1852
|
+
stateMutability: "pure"
|
|
1853
|
+
},
|
|
1854
|
+
{ type: "error", name: "NotAllowed", inputs: [] },
|
|
1855
|
+
{ type: "error", name: "SealingKeyInvalid", inputs: [] },
|
|
1856
|
+
{ type: "error", name: "SealingKeyMissing", inputs: [] }
|
|
1857
|
+
];
|
|
1858
|
+
|
|
1859
|
+
// core/decrypt/cofheMocksSealOutput.ts
|
|
1860
|
+
var MockQueryDecrypterAddress = "0x0000000000000000000000000000000000000200";
|
|
1861
|
+
async function cofheMocksSealOutput(ctHash, utype, permit, publicClient, mocksSealOutputDelay) {
|
|
1862
|
+
if (mocksSealOutputDelay > 0)
|
|
1863
|
+
await sleep(mocksSealOutputDelay);
|
|
1864
|
+
const permission = PermitUtils.getPermission(permit, true);
|
|
1865
|
+
const permissionWithBigInts = {
|
|
1866
|
+
...permission,
|
|
1867
|
+
expiration: BigInt(permission.expiration),
|
|
1868
|
+
validatorId: BigInt(permission.validatorId)
|
|
1869
|
+
};
|
|
1870
|
+
const [allowed, error, result] = await publicClient.readContract({
|
|
1871
|
+
address: MockQueryDecrypterAddress,
|
|
1872
|
+
abi: MockQueryDecrypterAbi,
|
|
1873
|
+
functionName: "querySealOutput",
|
|
1874
|
+
args: [ctHash, BigInt(utype), permissionWithBigInts]
|
|
1875
|
+
});
|
|
1876
|
+
if (error != "") {
|
|
1877
|
+
throw new CofhesdkError({
|
|
1878
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1879
|
+
message: `mocks querySealOutput call failed: ${error}`
|
|
1880
|
+
});
|
|
1539
1881
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1882
|
+
if (allowed == false) {
|
|
1883
|
+
throw new CofhesdkError({
|
|
1884
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1885
|
+
message: `mocks querySealOutput call failed: ACL Access Denied (NotAllowed)`
|
|
1886
|
+
});
|
|
1542
1887
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1888
|
+
const sealedBigInt = BigInt(result);
|
|
1889
|
+
const sealingKeyBigInt = BigInt(permission.sealingKey);
|
|
1890
|
+
const unsealed = sealedBigInt ^ sealingKeyBigInt;
|
|
1891
|
+
return unsealed;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// core/decrypt/tnSealOutputV2.ts
|
|
1895
|
+
var POLL_INTERVAL_MS = 1e3;
|
|
1896
|
+
var POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1897
|
+
function numberArrayToUint8Array(arr) {
|
|
1898
|
+
return new Uint8Array(arr);
|
|
1899
|
+
}
|
|
1900
|
+
function convertSealedData(sealed) {
|
|
1901
|
+
if (!sealed) {
|
|
1902
|
+
throw new CofhesdkError({
|
|
1903
|
+
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
1904
|
+
message: "Sealed data is missing from completed response"
|
|
1905
|
+
});
|
|
1551
1906
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1907
|
+
return {
|
|
1908
|
+
data: numberArrayToUint8Array(sealed.data),
|
|
1909
|
+
public_key: numberArrayToUint8Array(sealed.public_key),
|
|
1910
|
+
nonce: numberArrayToUint8Array(sealed.nonce)
|
|
1911
|
+
};
|
|
1912
|
+
}
|
|
1913
|
+
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission) {
|
|
1914
|
+
const body = {
|
|
1915
|
+
ct_tempkey: ctHash.toString(16).padStart(64, "0"),
|
|
1916
|
+
host_chain_id: chainId,
|
|
1917
|
+
permit: permission
|
|
1918
|
+
};
|
|
1919
|
+
let response;
|
|
1920
|
+
try {
|
|
1921
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
|
|
1922
|
+
method: "POST",
|
|
1923
|
+
headers: {
|
|
1924
|
+
"Content-Type": "application/json"
|
|
1925
|
+
},
|
|
1926
|
+
body: JSON.stringify(body)
|
|
1927
|
+
});
|
|
1928
|
+
} catch (e) {
|
|
1929
|
+
throw new CofhesdkError({
|
|
1930
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1931
|
+
message: `sealOutput request failed`,
|
|
1932
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
1933
|
+
cause: e instanceof Error ? e : void 0,
|
|
1934
|
+
context: {
|
|
1935
|
+
thresholdNetworkUrl,
|
|
1936
|
+
body
|
|
1937
|
+
}
|
|
1938
|
+
});
|
|
1557
1939
|
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
return this.tfhePublicKeyDeserializer;
|
|
1940
|
+
if (!response.ok) {
|
|
1941
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
1942
|
+
try {
|
|
1943
|
+
const errorBody = await response.json();
|
|
1944
|
+
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
1945
|
+
} catch {
|
|
1946
|
+
errorMessage = response.statusText || errorMessage;
|
|
1947
|
+
}
|
|
1567
1948
|
throw new CofhesdkError({
|
|
1568
|
-
code: "
|
|
1569
|
-
message:
|
|
1570
|
-
hint: "
|
|
1949
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1950
|
+
message: `sealOutput request failed: ${errorMessage}`,
|
|
1951
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
1571
1952
|
context: {
|
|
1572
|
-
|
|
1953
|
+
thresholdNetworkUrl,
|
|
1954
|
+
status: response.status,
|
|
1955
|
+
statusText: response.statusText,
|
|
1956
|
+
body
|
|
1573
1957
|
}
|
|
1574
1958
|
});
|
|
1575
1959
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
* Users should not set this manually.
|
|
1581
|
-
*/
|
|
1582
|
-
getCompactPkeCrsDeserializerOrThrow() {
|
|
1583
|
-
if (this.compactPkeCrsDeserializer)
|
|
1584
|
-
return this.compactPkeCrsDeserializer;
|
|
1960
|
+
let submitResponse;
|
|
1961
|
+
try {
|
|
1962
|
+
submitResponse = await response.json();
|
|
1963
|
+
} catch (e) {
|
|
1585
1964
|
throw new CofhesdkError({
|
|
1586
|
-
code: "
|
|
1587
|
-
message:
|
|
1588
|
-
|
|
1965
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1966
|
+
message: `Failed to parse sealOutput submit response`,
|
|
1967
|
+
cause: e instanceof Error ? e : void 0,
|
|
1589
1968
|
context: {
|
|
1590
|
-
|
|
1969
|
+
thresholdNetworkUrl,
|
|
1970
|
+
body
|
|
1591
1971
|
}
|
|
1592
1972
|
});
|
|
1593
1973
|
}
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1974
|
+
if (!submitResponse.request_id) {
|
|
1975
|
+
throw new CofhesdkError({
|
|
1976
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1977
|
+
message: `sealOutput submit response missing request_id`,
|
|
1978
|
+
context: {
|
|
1979
|
+
thresholdNetworkUrl,
|
|
1980
|
+
body,
|
|
1981
|
+
submitResponse
|
|
1982
|
+
}
|
|
1983
|
+
});
|
|
1602
1984
|
}
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
} catch (error) {
|
|
1615
|
-
throw CofhesdkError.fromError(error, {
|
|
1616
|
-
code: "INIT_TFHE_FAILED" /* InitTfheFailed */,
|
|
1617
|
-
message: `Failed to initialize TFHE`,
|
|
1985
|
+
return submitResponse.request_id;
|
|
1986
|
+
}
|
|
1987
|
+
async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
1988
|
+
const startTime = Date.now();
|
|
1989
|
+
let completed = false;
|
|
1990
|
+
while (!completed) {
|
|
1991
|
+
if (Date.now() - startTime > POLL_TIMEOUT_MS) {
|
|
1992
|
+
throw new CofhesdkError({
|
|
1993
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
1994
|
+
message: `sealOutput polling timed out after ${POLL_TIMEOUT_MS}ms`,
|
|
1995
|
+
hint: "The request may still be processing. Try again later.",
|
|
1618
1996
|
context: {
|
|
1619
|
-
|
|
1997
|
+
thresholdNetworkUrl,
|
|
1998
|
+
requestId,
|
|
1999
|
+
timeoutMs: POLL_TIMEOUT_MS
|
|
1620
2000
|
}
|
|
1621
2001
|
});
|
|
1622
2002
|
}
|
|
1623
|
-
|
|
1624
|
-
/**
|
|
1625
|
-
* Fetches the FHE key and CRS from the CoFHE API
|
|
1626
|
-
* If the key/crs already exists in the store it is returned, else it is fetched, stored, and returned
|
|
1627
|
-
*/
|
|
1628
|
-
async fetchFheKeyAndCrs() {
|
|
1629
|
-
const config = this.getConfigOrThrow();
|
|
1630
|
-
const chainId = await this.getChainIdOrThrow();
|
|
1631
|
-
const compactPkeCrsDeserializer = this.getCompactPkeCrsDeserializerOrThrow();
|
|
1632
|
-
const tfhePublicKeyDeserializer = this.getTfhePublicKeyDeserializerOrThrow();
|
|
1633
|
-
const securityZone = this.getSecurityZone();
|
|
2003
|
+
let response;
|
|
1634
2004
|
try {
|
|
1635
|
-
await
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
2005
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput/${requestId}`, {
|
|
2006
|
+
method: "GET",
|
|
2007
|
+
headers: {
|
|
2008
|
+
"Content-Type": "application/json"
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
} catch (e) {
|
|
2012
|
+
throw new CofhesdkError({
|
|
2013
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2014
|
+
message: `sealOutput status poll failed`,
|
|
2015
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2016
|
+
cause: e instanceof Error ? e : void 0,
|
|
1640
2017
|
context: {
|
|
1641
|
-
|
|
2018
|
+
thresholdNetworkUrl,
|
|
2019
|
+
requestId
|
|
1642
2020
|
}
|
|
1643
2021
|
});
|
|
1644
2022
|
}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
[[fheKey, fheKeyFetchedFromCoFHE], [crs, crsFetchedFromCoFHE]] = await fetchKeys(
|
|
1651
|
-
config,
|
|
1652
|
-
chainId,
|
|
1653
|
-
securityZone,
|
|
1654
|
-
tfhePublicKeyDeserializer,
|
|
1655
|
-
compactPkeCrsDeserializer,
|
|
1656
|
-
this.keysStorage
|
|
1657
|
-
);
|
|
1658
|
-
} catch (error) {
|
|
1659
|
-
throw CofhesdkError.fromError(error, {
|
|
1660
|
-
code: "FETCH_KEYS_FAILED" /* FetchKeysFailed */,
|
|
1661
|
-
message: `Failed to fetch FHE key and CRS`,
|
|
2023
|
+
if (response.status === 404) {
|
|
2024
|
+
throw new CofhesdkError({
|
|
2025
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2026
|
+
message: `sealOutput request not found: ${requestId}`,
|
|
2027
|
+
hint: "The request may have expired or been invalid.",
|
|
1662
2028
|
context: {
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
securityZone,
|
|
1666
|
-
compactPkeCrsDeserializer,
|
|
1667
|
-
tfhePublicKeyDeserializer
|
|
2029
|
+
thresholdNetworkUrl,
|
|
2030
|
+
requestId
|
|
1668
2031
|
}
|
|
1669
2032
|
});
|
|
1670
2033
|
}
|
|
1671
|
-
if (!
|
|
2034
|
+
if (!response.ok) {
|
|
2035
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
2036
|
+
try {
|
|
2037
|
+
const errorBody = await response.json();
|
|
2038
|
+
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
2039
|
+
} catch {
|
|
2040
|
+
errorMessage = response.statusText || errorMessage;
|
|
2041
|
+
}
|
|
1672
2042
|
throw new CofhesdkError({
|
|
1673
|
-
code: "
|
|
1674
|
-
message: `
|
|
2043
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2044
|
+
message: `sealOutput status poll failed: ${errorMessage}`,
|
|
1675
2045
|
context: {
|
|
1676
|
-
|
|
1677
|
-
|
|
2046
|
+
thresholdNetworkUrl,
|
|
2047
|
+
requestId,
|
|
2048
|
+
status: response.status,
|
|
2049
|
+
statusText: response.statusText
|
|
1678
2050
|
}
|
|
1679
2051
|
});
|
|
1680
2052
|
}
|
|
1681
|
-
|
|
2053
|
+
let statusResponse;
|
|
2054
|
+
try {
|
|
2055
|
+
statusResponse = await response.json();
|
|
2056
|
+
} catch (e) {
|
|
1682
2057
|
throw new CofhesdkError({
|
|
1683
|
-
code: "
|
|
1684
|
-
message: `
|
|
2058
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2059
|
+
message: `Failed to parse sealOutput status response`,
|
|
2060
|
+
cause: e instanceof Error ? e : void 0,
|
|
1685
2061
|
context: {
|
|
1686
|
-
|
|
2062
|
+
thresholdNetworkUrl,
|
|
2063
|
+
requestId
|
|
1687
2064
|
}
|
|
1688
2065
|
});
|
|
1689
2066
|
}
|
|
1690
|
-
|
|
2067
|
+
if (statusResponse.status === "COMPLETED") {
|
|
2068
|
+
if (statusResponse.is_succeed === false) {
|
|
2069
|
+
const errorMessage = statusResponse.error_message || "Unknown error";
|
|
2070
|
+
throw new CofhesdkError({
|
|
2071
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2072
|
+
message: `sealOutput request failed: ${errorMessage}`,
|
|
2073
|
+
context: {
|
|
2074
|
+
thresholdNetworkUrl,
|
|
2075
|
+
requestId,
|
|
2076
|
+
statusResponse
|
|
2077
|
+
}
|
|
2078
|
+
});
|
|
2079
|
+
}
|
|
2080
|
+
if (!statusResponse.sealed) {
|
|
2081
|
+
throw new CofhesdkError({
|
|
2082
|
+
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2083
|
+
message: `sealOutput request completed but returned no sealed data`,
|
|
2084
|
+
context: {
|
|
2085
|
+
thresholdNetworkUrl,
|
|
2086
|
+
requestId,
|
|
2087
|
+
statusResponse
|
|
2088
|
+
}
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2091
|
+
return convertSealedData(statusResponse.sealed);
|
|
2092
|
+
}
|
|
2093
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
2094
|
+
}
|
|
2095
|
+
throw new CofhesdkError({
|
|
2096
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2097
|
+
message: "Polling loop exited unexpectedly",
|
|
2098
|
+
context: {
|
|
2099
|
+
thresholdNetworkUrl,
|
|
2100
|
+
requestId
|
|
2101
|
+
}
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
async function tnSealOutputV2(ctHash, chainId, permission, thresholdNetworkUrl) {
|
|
2105
|
+
const requestId = await submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission);
|
|
2106
|
+
return await pollSealOutputStatus(thresholdNetworkUrl, requestId);
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
// core/decrypt/decryptHandleBuilder.ts
|
|
2110
|
+
var DecryptHandlesBuilder = class extends BaseBuilder {
|
|
2111
|
+
ctHash;
|
|
2112
|
+
utype;
|
|
2113
|
+
permitHash;
|
|
2114
|
+
permit;
|
|
2115
|
+
constructor(params) {
|
|
2116
|
+
super({
|
|
2117
|
+
config: params.config,
|
|
2118
|
+
publicClient: params.publicClient,
|
|
2119
|
+
walletClient: params.walletClient,
|
|
2120
|
+
chainId: params.chainId,
|
|
2121
|
+
account: params.account,
|
|
2122
|
+
requireConnected: params.requireConnected
|
|
2123
|
+
});
|
|
2124
|
+
this.ctHash = params.ctHash;
|
|
2125
|
+
this.utype = params.utype;
|
|
2126
|
+
this.permitHash = params.permitHash;
|
|
2127
|
+
this.permit = params.permit;
|
|
1691
2128
|
}
|
|
1692
2129
|
/**
|
|
1693
|
-
*
|
|
1694
|
-
* web/ uses zama "tfhe"
|
|
1695
|
-
* node/ uses zama "node-tfhe"
|
|
1696
|
-
* Users should not set this manually.
|
|
2130
|
+
* @param chainId - Chain to decrypt values from. Used to fetch the threshold network URL and use the correct permit.
|
|
1697
2131
|
*
|
|
1698
|
-
*
|
|
1699
|
-
*/
|
|
1700
|
-
generateZkBuilderAndCrs(fheKey, crs) {
|
|
1701
|
-
const zkBuilderAndCrsGenerator = this.zkBuilderAndCrsGenerator;
|
|
1702
|
-
if (!zkBuilderAndCrsGenerator) {
|
|
1703
|
-
throw new CofhesdkError({
|
|
1704
|
-
code: "MISSING_ZK_BUILDER_AND_CRS_GENERATOR" /* MissingZkBuilderAndCrsGenerator */,
|
|
1705
|
-
message: `zkBuilderAndCrsGenerator is undefined`,
|
|
1706
|
-
hint: "Ensure client has been created with a zkBuilderAndCrsGenerator.",
|
|
1707
|
-
context: {
|
|
1708
|
-
zkBuilderAndCrsGenerator: this.zkBuilderAndCrsGenerator
|
|
1709
|
-
}
|
|
1710
|
-
});
|
|
1711
|
-
}
|
|
1712
|
-
return zkBuilderAndCrsGenerator(fheKey, crs);
|
|
1713
|
-
}
|
|
1714
|
-
/**
|
|
1715
|
-
* @dev Encrypt against the cofheMocks instead of CoFHE
|
|
2132
|
+
* If not provided, the chainId will be fetched from the connected publicClient.
|
|
1716
2133
|
*
|
|
1717
|
-
*
|
|
1718
|
-
*
|
|
1719
|
-
*
|
|
2134
|
+
* Example:
|
|
2135
|
+
* ```typescript
|
|
2136
|
+
* const unsealed = await decryptHandle(ctHash, utype)
|
|
2137
|
+
* .setChainId(11155111)
|
|
2138
|
+
* .decrypt();
|
|
2139
|
+
* ```
|
|
2140
|
+
*
|
|
2141
|
+
* @returns The chainable DecryptHandlesBuilder instance.
|
|
1720
2142
|
*/
|
|
1721
|
-
|
|
1722
|
-
this.
|
|
1723
|
-
|
|
1724
|
-
this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted: false });
|
|
1725
|
-
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1726
|
-
await sleep(100);
|
|
1727
|
-
this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE: false, crsFetchedFromCoFHE: false });
|
|
1728
|
-
this.fireStepStart("pack" /* Pack */);
|
|
1729
|
-
await cofheMocksCheckEncryptableBits(this.inputItems);
|
|
1730
|
-
await sleep(100);
|
|
1731
|
-
this.fireStepEnd("pack" /* Pack */);
|
|
1732
|
-
this.fireStepStart("prove" /* Prove */);
|
|
1733
|
-
await sleep(500);
|
|
1734
|
-
this.fireStepEnd("prove" /* Prove */);
|
|
1735
|
-
this.fireStepStart("verify" /* Verify */);
|
|
1736
|
-
await sleep(500);
|
|
1737
|
-
const signedResults = await cofheMocksZkVerifySign(
|
|
1738
|
-
this.inputItems,
|
|
1739
|
-
account,
|
|
1740
|
-
this.securityZone,
|
|
1741
|
-
this.getPublicClientOrThrow(),
|
|
1742
|
-
this.getWalletClientOrThrow(),
|
|
1743
|
-
this.zkvWalletClient
|
|
1744
|
-
);
|
|
1745
|
-
const encryptedInputs = signedResults.map(({ ct_hash, signature }, index) => ({
|
|
1746
|
-
ctHash: BigInt(ct_hash),
|
|
1747
|
-
securityZone: this.securityZone,
|
|
1748
|
-
utype: this.inputItems[index].utype,
|
|
1749
|
-
signature
|
|
1750
|
-
}));
|
|
1751
|
-
this.fireStepEnd("verify" /* Verify */);
|
|
1752
|
-
return encryptedInputs;
|
|
2143
|
+
setChainId(chainId) {
|
|
2144
|
+
this.chainId = chainId;
|
|
2145
|
+
return this;
|
|
1753
2146
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
*/
|
|
1757
|
-
async productionEncrypt(account, chainId) {
|
|
1758
|
-
this.fireStepStart("initTfhe" /* InitTfhe */);
|
|
1759
|
-
const tfheInitializationExecuted = await this.initTfheOrThrow();
|
|
1760
|
-
this.fireStepEnd("initTfhe" /* InitTfhe */, { tfheInitializationExecuted });
|
|
1761
|
-
this.fireStepStart("fetchKeys" /* FetchKeys */);
|
|
1762
|
-
const { fheKey, fheKeyFetchedFromCoFHE, crs, crsFetchedFromCoFHE } = await this.fetchFheKeyAndCrs();
|
|
1763
|
-
let { zkBuilder, zkCrs } = this.generateZkBuilderAndCrs(fheKey, crs);
|
|
1764
|
-
this.fireStepEnd("fetchKeys" /* FetchKeys */, { fheKeyFetchedFromCoFHE, crsFetchedFromCoFHE });
|
|
1765
|
-
this.fireStepStart("pack" /* Pack */);
|
|
1766
|
-
zkBuilder = zkPack(this.inputItems, zkBuilder);
|
|
1767
|
-
this.fireStepEnd("pack" /* Pack */);
|
|
1768
|
-
this.fireStepStart("prove" /* Prove */);
|
|
1769
|
-
const proof = await zkProve(zkBuilder, zkCrs, account, this.securityZone, chainId);
|
|
1770
|
-
this.fireStepEnd("prove" /* Prove */);
|
|
1771
|
-
this.fireStepStart("verify" /* Verify */);
|
|
1772
|
-
const zkVerifierUrl = await this.getZkVerifierUrl();
|
|
1773
|
-
const verifyResults = await zkVerify(zkVerifierUrl, proof, account, this.securityZone, chainId);
|
|
1774
|
-
const encryptedInputs = verifyResults.map(
|
|
1775
|
-
({ ct_hash, signature }, index) => ({
|
|
1776
|
-
ctHash: BigInt(ct_hash),
|
|
1777
|
-
securityZone: this.securityZone,
|
|
1778
|
-
utype: this.inputItems[index].utype,
|
|
1779
|
-
signature
|
|
1780
|
-
})
|
|
1781
|
-
);
|
|
1782
|
-
this.fireStepEnd("verify" /* Verify */);
|
|
1783
|
-
return encryptedInputs;
|
|
2147
|
+
getChainId() {
|
|
2148
|
+
return this.chainId;
|
|
1784
2149
|
}
|
|
1785
2150
|
/**
|
|
1786
|
-
*
|
|
2151
|
+
* @param account - Account to decrypt values from. Used to fetch the correct permit.
|
|
1787
2152
|
*
|
|
1788
|
-
*
|
|
1789
|
-
* - Pack the encryptable items into a zk proof
|
|
1790
|
-
* - Prove the zk proof
|
|
1791
|
-
* - Verify the zk proof with CoFHE
|
|
1792
|
-
* - Package and return the encrypted inputs
|
|
2153
|
+
* If not provided, the account will be fetched from the connected walletClient.
|
|
1793
2154
|
*
|
|
1794
2155
|
* Example:
|
|
1795
2156
|
* ```typescript
|
|
1796
|
-
* const
|
|
1797
|
-
* .setAccount('
|
|
1798
|
-
* .
|
|
1799
|
-
*
|
|
1800
|
-
*
|
|
1801
|
-
*
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
return
|
|
1806
|
-
await this.requireConnectedOrThrow();
|
|
1807
|
-
const account = await this.getAccountOrThrow();
|
|
1808
|
-
const chainId = await this.getChainIdOrThrow();
|
|
1809
|
-
if (chainId === hardhat$1.id) {
|
|
1810
|
-
return await this.mocksEncrypt(account);
|
|
1811
|
-
}
|
|
1812
|
-
return await this.productionEncrypt(account, chainId);
|
|
1813
|
-
});
|
|
1814
|
-
}
|
|
1815
|
-
};
|
|
1816
|
-
|
|
1817
|
-
// core/types.ts
|
|
1818
|
-
var FheTypes = /* @__PURE__ */ ((FheTypes2) => {
|
|
1819
|
-
FheTypes2[FheTypes2["Bool"] = 0] = "Bool";
|
|
1820
|
-
FheTypes2[FheTypes2["Uint4"] = 1] = "Uint4";
|
|
1821
|
-
FheTypes2[FheTypes2["Uint8"] = 2] = "Uint8";
|
|
1822
|
-
FheTypes2[FheTypes2["Uint16"] = 3] = "Uint16";
|
|
1823
|
-
FheTypes2[FheTypes2["Uint32"] = 4] = "Uint32";
|
|
1824
|
-
FheTypes2[FheTypes2["Uint64"] = 5] = "Uint64";
|
|
1825
|
-
FheTypes2[FheTypes2["Uint128"] = 6] = "Uint128";
|
|
1826
|
-
FheTypes2[FheTypes2["Uint160"] = 7] = "Uint160";
|
|
1827
|
-
FheTypes2[FheTypes2["Uint256"] = 8] = "Uint256";
|
|
1828
|
-
FheTypes2[FheTypes2["Uint512"] = 9] = "Uint512";
|
|
1829
|
-
FheTypes2[FheTypes2["Uint1024"] = 10] = "Uint1024";
|
|
1830
|
-
FheTypes2[FheTypes2["Uint2048"] = 11] = "Uint2048";
|
|
1831
|
-
FheTypes2[FheTypes2["Uint2"] = 12] = "Uint2";
|
|
1832
|
-
FheTypes2[FheTypes2["Uint6"] = 13] = "Uint6";
|
|
1833
|
-
FheTypes2[FheTypes2["Uint10"] = 14] = "Uint10";
|
|
1834
|
-
FheTypes2[FheTypes2["Uint12"] = 15] = "Uint12";
|
|
1835
|
-
FheTypes2[FheTypes2["Uint14"] = 16] = "Uint14";
|
|
1836
|
-
FheTypes2[FheTypes2["Int2"] = 17] = "Int2";
|
|
1837
|
-
FheTypes2[FheTypes2["Int4"] = 18] = "Int4";
|
|
1838
|
-
FheTypes2[FheTypes2["Int6"] = 19] = "Int6";
|
|
1839
|
-
FheTypes2[FheTypes2["Int8"] = 20] = "Int8";
|
|
1840
|
-
FheTypes2[FheTypes2["Int10"] = 21] = "Int10";
|
|
1841
|
-
FheTypes2[FheTypes2["Int12"] = 22] = "Int12";
|
|
1842
|
-
FheTypes2[FheTypes2["Int14"] = 23] = "Int14";
|
|
1843
|
-
FheTypes2[FheTypes2["Int16"] = 24] = "Int16";
|
|
1844
|
-
FheTypes2[FheTypes2["Int32"] = 25] = "Int32";
|
|
1845
|
-
FheTypes2[FheTypes2["Int64"] = 26] = "Int64";
|
|
1846
|
-
FheTypes2[FheTypes2["Int128"] = 27] = "Int128";
|
|
1847
|
-
FheTypes2[FheTypes2["Int160"] = 28] = "Int160";
|
|
1848
|
-
FheTypes2[FheTypes2["Int256"] = 29] = "Int256";
|
|
1849
|
-
return FheTypes2;
|
|
1850
|
-
})(FheTypes || {});
|
|
1851
|
-
var FheUintUTypes = [
|
|
1852
|
-
2 /* Uint8 */,
|
|
1853
|
-
3 /* Uint16 */,
|
|
1854
|
-
4 /* Uint32 */,
|
|
1855
|
-
5 /* Uint64 */,
|
|
1856
|
-
6 /* Uint128 */
|
|
1857
|
-
// [U256-DISABLED]
|
|
1858
|
-
// FheTypes.Uint256,
|
|
1859
|
-
];
|
|
1860
|
-
var FheAllUTypes = [
|
|
1861
|
-
0 /* Bool */,
|
|
1862
|
-
2 /* Uint8 */,
|
|
1863
|
-
3 /* Uint16 */,
|
|
1864
|
-
4 /* Uint32 */,
|
|
1865
|
-
5 /* Uint64 */,
|
|
1866
|
-
6 /* Uint128 */,
|
|
1867
|
-
// [U256-DISABLED]
|
|
1868
|
-
// FheTypes.Uint256,
|
|
1869
|
-
7 /* Uint160 */
|
|
1870
|
-
];
|
|
1871
|
-
var Encryptable = {
|
|
1872
|
-
bool: (data, securityZone = 0) => ({ data, securityZone, utype: 0 /* Bool */ }),
|
|
1873
|
-
address: (data, securityZone = 0) => ({ data, securityZone, utype: 7 /* Uint160 */ }),
|
|
1874
|
-
uint8: (data, securityZone = 0) => ({ data, securityZone, utype: 2 /* Uint8 */ }),
|
|
1875
|
-
uint16: (data, securityZone = 0) => ({ data, securityZone, utype: 3 /* Uint16 */ }),
|
|
1876
|
-
uint32: (data, securityZone = 0) => ({ data, securityZone, utype: 4 /* Uint32 */ }),
|
|
1877
|
-
uint64: (data, securityZone = 0) => ({ data, securityZone, utype: 5 /* Uint64 */ }),
|
|
1878
|
-
uint128: (data, securityZone = 0) => ({ data, securityZone, utype: 6 /* Uint128 */ })
|
|
1879
|
-
// [U256-DISABLED]
|
|
1880
|
-
// uint256: (data: EncryptableUint256['data'], securityZone = 0) =>
|
|
1881
|
-
// ({ data, securityZone, utype: FheTypes.Uint256 }) as EncryptableUint256,
|
|
1882
|
-
};
|
|
1883
|
-
function isEncryptableItem(value) {
|
|
1884
|
-
return (
|
|
1885
|
-
// Is object and exists
|
|
1886
|
-
typeof value === "object" && value !== null && // Has securityZone
|
|
1887
|
-
"securityZone" in value && typeof value.securityZone === "number" && // Has utype
|
|
1888
|
-
"utype" in value && FheAllUTypes.includes(value.utype) && // Has data
|
|
1889
|
-
"data" in value && ["string", "number", "bigint", "boolean"].includes(typeof value.data)
|
|
1890
|
-
);
|
|
1891
|
-
}
|
|
1892
|
-
var EncryptStep = /* @__PURE__ */ ((EncryptStep2) => {
|
|
1893
|
-
EncryptStep2["InitTfhe"] = "initTfhe";
|
|
1894
|
-
EncryptStep2["FetchKeys"] = "fetchKeys";
|
|
1895
|
-
EncryptStep2["Pack"] = "pack";
|
|
1896
|
-
EncryptStep2["Prove"] = "prove";
|
|
1897
|
-
EncryptStep2["Verify"] = "verify";
|
|
1898
|
-
return EncryptStep2;
|
|
1899
|
-
})(EncryptStep || {});
|
|
1900
|
-
|
|
1901
|
-
// core/config.ts
|
|
1902
|
-
var CofhesdkConfigSchema = z.object({
|
|
1903
|
-
/** List of supported chain configurations */
|
|
1904
|
-
supportedChains: z.array(z.custom()),
|
|
1905
|
-
/** Strategy for fetching FHE keys */
|
|
1906
|
-
fheKeysPrefetching: z.enum(["CONNECTED_CHAIN", "SUPPORTED_CHAINS", "OFF"]).optional().default("OFF"),
|
|
1907
|
-
/** How permits are generated */
|
|
1908
|
-
permitGeneration: z.enum(["ON_CONNECT", "ON_DECRYPT_HANDLES", "MANUAL"]).optional().default("ON_CONNECT"),
|
|
1909
|
-
/** Default permit expiration in seconds, default is 30 days */
|
|
1910
|
-
defaultPermitExpiration: z.number().optional().default(60 * 60 * 24 * 30),
|
|
1911
|
-
/** Storage method for fhe keys (defaults to indexedDB on web, filesystem on node) */
|
|
1912
|
-
fheKeyStorage: z.object({
|
|
1913
|
-
getItem: z.function().args(z.string()).returns(z.promise(z.any())),
|
|
1914
|
-
setItem: z.function().args(z.string(), z.any()).returns(z.promise(z.void())),
|
|
1915
|
-
removeItem: z.function().args(z.string()).returns(z.promise(z.void()))
|
|
1916
|
-
}).or(z.null()).default(null),
|
|
1917
|
-
/** Mocks configs */
|
|
1918
|
-
mocks: z.object({
|
|
1919
|
-
sealOutputDelay: z.number().optional().default(0)
|
|
1920
|
-
}).optional().default({ sealOutputDelay: 0 }),
|
|
1921
|
-
/** Internal configuration */
|
|
1922
|
-
_internal: z.object({
|
|
1923
|
-
zkvWalletClient: z.any().optional()
|
|
1924
|
-
}).optional()
|
|
1925
|
-
});
|
|
1926
|
-
function createCofhesdkConfigBase(config) {
|
|
1927
|
-
const result = CofhesdkConfigSchema.safeParse(config);
|
|
1928
|
-
if (!result.success) {
|
|
1929
|
-
throw new Error(`Invalid cofhesdk configuration: ${result.error.message}`);
|
|
1930
|
-
}
|
|
1931
|
-
return result.data;
|
|
1932
|
-
}
|
|
1933
|
-
var getCofhesdkConfigItem = (config, key) => {
|
|
1934
|
-
return config[key];
|
|
1935
|
-
};
|
|
1936
|
-
function getSupportedChainOrThrow(config, chainId) {
|
|
1937
|
-
const supportedChain = config.supportedChains.find((chain) => chain.id === chainId);
|
|
1938
|
-
if (!supportedChain) {
|
|
1939
|
-
throw new CofhesdkError({
|
|
1940
|
-
code: "UNSUPPORTED_CHAIN" /* UnsupportedChain */,
|
|
1941
|
-
message: `Config does not support chain <${chainId}>`,
|
|
1942
|
-
hint: "Ensure config passed to client has been created with this chain in the config.supportedChains array.",
|
|
1943
|
-
context: {
|
|
1944
|
-
chainId,
|
|
1945
|
-
supportedChainIds: config.supportedChains.map((c) => c.id)
|
|
1946
|
-
}
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
return supportedChain;
|
|
1950
|
-
}
|
|
1951
|
-
function getCoFheUrlOrThrow(config, chainId) {
|
|
1952
|
-
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
1953
|
-
const url = supportedChain.coFheUrl;
|
|
1954
|
-
if (!url) {
|
|
1955
|
-
throw new CofhesdkError({
|
|
1956
|
-
code: "MISSING_CONFIG" /* MissingConfig */,
|
|
1957
|
-
message: `CoFHE URL is not configured for chain <${chainId}>`,
|
|
1958
|
-
hint: "Ensure this chain config includes a coFheUrl property.",
|
|
1959
|
-
context: { chainId }
|
|
1960
|
-
});
|
|
2157
|
+
* const unsealed = await decryptHandle(ctHash, utype)
|
|
2158
|
+
* .setAccount('0x1234567890123456789012345678901234567890')
|
|
2159
|
+
* .decrypt();
|
|
2160
|
+
* ```
|
|
2161
|
+
*
|
|
2162
|
+
* @returns The chainable DecryptHandlesBuilder instance.
|
|
2163
|
+
*/
|
|
2164
|
+
setAccount(account) {
|
|
2165
|
+
this.account = account;
|
|
2166
|
+
return this;
|
|
1961
2167
|
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
function getZkVerifierUrlOrThrow(config, chainId) {
|
|
1965
|
-
const supportedChain = getSupportedChainOrThrow(config, chainId);
|
|
1966
|
-
const url = supportedChain.verifierUrl;
|
|
1967
|
-
if (!url) {
|
|
1968
|
-
throw new CofhesdkError({
|
|
1969
|
-
code: "ZK_VERIFIER_URL_UNINITIALIZED" /* ZkVerifierUrlUninitialized */,
|
|
1970
|
-
message: `ZK verifier URL is not configured for chain <${chainId}>`,
|
|
1971
|
-
hint: "Ensure this chain config includes a verifierUrl property.",
|
|
1972
|
-
context: { chainId }
|
|
1973
|
-
});
|
|
2168
|
+
getAccount() {
|
|
2169
|
+
return this.account;
|
|
1974
2170
|
}
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
2171
|
+
/**
|
|
2172
|
+
* @param permitHash - Permit hash to decrypt values from. Used to fetch the correct permit.
|
|
2173
|
+
*
|
|
2174
|
+
* If not provided, the active permit for the chainId and account will be used.
|
|
2175
|
+
* If `setPermit()` is called, it will be used regardless of chainId, account, or permitHash.
|
|
2176
|
+
*
|
|
2177
|
+
* Example:
|
|
2178
|
+
* ```typescript
|
|
2179
|
+
* const unsealed = await decryptHandle(ctHash, utype)
|
|
2180
|
+
* .setPermitHash('0x1234567890123456789012345678901234567890')
|
|
2181
|
+
* .decrypt();
|
|
2182
|
+
* ```
|
|
2183
|
+
*
|
|
2184
|
+
* @returns The chainable DecryptHandlesBuilder instance.
|
|
2185
|
+
*/
|
|
2186
|
+
setPermitHash(permitHash) {
|
|
2187
|
+
this.permitHash = permitHash;
|
|
2188
|
+
return this;
|
|
1987
2189
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
// core/fetchKeys.ts
|
|
1992
|
-
var PUBLIC_KEY_LENGTH_MIN = 15e3;
|
|
1993
|
-
var checkKeyValidity = (key, serializer) => {
|
|
1994
|
-
if (key == null || key.length === 0)
|
|
1995
|
-
return [false, `Key is null or empty <${key}>`];
|
|
1996
|
-
try {
|
|
1997
|
-
serializer(key);
|
|
1998
|
-
return [true, `Key is valid`];
|
|
1999
|
-
} catch (err) {
|
|
2000
|
-
return [false, `Serialization failed <${err}> key length <${key.length}>`];
|
|
2190
|
+
getPermitHash() {
|
|
2191
|
+
return this.permitHash;
|
|
2001
2192
|
}
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
} catch (err) {
|
|
2020
|
-
throw new Error(`Error fetching FHE publicKey; fetching from CoFHE failed with error ${err}`);
|
|
2193
|
+
/**
|
|
2194
|
+
* @param permit - Permit to decrypt values with. If provided, it will be used regardless of chainId, account, or permitHash.
|
|
2195
|
+
*
|
|
2196
|
+
* If not provided, the permit will be determined by chainId, account, and permitHash.
|
|
2197
|
+
*
|
|
2198
|
+
* Example:
|
|
2199
|
+
* ```typescript
|
|
2200
|
+
* const unsealed = await decryptHandle(ctHash, utype)
|
|
2201
|
+
* .setPermit(permit)
|
|
2202
|
+
* .decrypt();
|
|
2203
|
+
* ```
|
|
2204
|
+
*
|
|
2205
|
+
* @returns The chainable DecryptHandlesBuilder instance.
|
|
2206
|
+
*/
|
|
2207
|
+
setPermit(permit) {
|
|
2208
|
+
this.permit = permit;
|
|
2209
|
+
return this;
|
|
2021
2210
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2211
|
+
getPermit() {
|
|
2212
|
+
return this.permit;
|
|
2024
2213
|
}
|
|
2025
|
-
|
|
2026
|
-
|
|
2214
|
+
async getThresholdNetworkUrl() {
|
|
2215
|
+
this.assertChainId();
|
|
2216
|
+
return getThresholdNetworkUrlOrThrow(this.config, this.chainId);
|
|
2027
2217
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2218
|
+
validateUtypeOrThrow() {
|
|
2219
|
+
if (!isValidUtype(this.utype))
|
|
2220
|
+
throw new CofhesdkError({
|
|
2221
|
+
code: "INVALID_UTYPE" /* InvalidUtype */,
|
|
2222
|
+
message: `Invalid utype to decrypt to`,
|
|
2223
|
+
context: {
|
|
2224
|
+
utype: this.utype
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2032
2227
|
}
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2228
|
+
async getResolvedPermit() {
|
|
2229
|
+
if (this.permit)
|
|
2230
|
+
return this.permit;
|
|
2231
|
+
this.assertChainId();
|
|
2232
|
+
this.assertAccount();
|
|
2233
|
+
if (this.permitHash) {
|
|
2234
|
+
const permit2 = await permits.getPermit(this.chainId, this.account, this.permitHash);
|
|
2235
|
+
if (!permit2) {
|
|
2236
|
+
throw new CofhesdkError({
|
|
2237
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2238
|
+
message: `Permit with hash <${this.permitHash}> not found for account <${this.account}> and chainId <${this.chainId}>`,
|
|
2239
|
+
hint: "Ensure the permit exists and is valid.",
|
|
2240
|
+
context: {
|
|
2241
|
+
chainId: this.chainId,
|
|
2242
|
+
account: this.account,
|
|
2243
|
+
permitHash: this.permitHash
|
|
2244
|
+
}
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
return permit2;
|
|
2248
|
+
}
|
|
2249
|
+
const permit = await permits.getActivePermit(this.chainId, this.account);
|
|
2250
|
+
if (!permit) {
|
|
2251
|
+
throw new CofhesdkError({
|
|
2252
|
+
code: "PERMIT_NOT_FOUND" /* PermitNotFound */,
|
|
2253
|
+
message: `Active permit not found for chainId <${this.chainId}> and account <${this.account}>`,
|
|
2254
|
+
hint: "Ensure a permit exists for this account on this chain.",
|
|
2255
|
+
context: {
|
|
2256
|
+
chainId: this.chainId,
|
|
2257
|
+
account: this.account
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
return permit;
|
|
2037
2262
|
}
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
return [storedKey, false];
|
|
2046
|
-
let crs_data = void 0;
|
|
2047
|
-
try {
|
|
2048
|
-
const crs_res = await fetch(`${coFheUrl}/GetCrs`, {
|
|
2049
|
-
method: "POST",
|
|
2050
|
-
headers: {
|
|
2051
|
-
"Content-Type": "application/json"
|
|
2052
|
-
},
|
|
2053
|
-
body: JSON.stringify({ securityZone })
|
|
2054
|
-
});
|
|
2055
|
-
const json = await crs_res.json();
|
|
2056
|
-
crs_data = json.crs;
|
|
2057
|
-
} catch (err) {
|
|
2058
|
-
throw new Error(`Error fetching CRS; fetching failed with error ${err}`);
|
|
2263
|
+
/**
|
|
2264
|
+
* On hardhat, interact with MockZkVerifier contract instead of CoFHE
|
|
2265
|
+
*/
|
|
2266
|
+
async mocksSealOutput(permit) {
|
|
2267
|
+
this.assertPublicClient();
|
|
2268
|
+
const mocksSealOutputDelay = this.config.mocks.sealOutputDelay;
|
|
2269
|
+
return cofheMocksSealOutput(this.ctHash, this.utype, permit, this.publicClient, mocksSealOutputDelay);
|
|
2059
2270
|
}
|
|
2060
|
-
|
|
2061
|
-
|
|
2271
|
+
/**
|
|
2272
|
+
* In the production context, perform a true decryption with the CoFHE coprocessor.
|
|
2273
|
+
*/
|
|
2274
|
+
async productionSealOutput(permit) {
|
|
2275
|
+
this.assertChainId();
|
|
2276
|
+
this.assertPublicClient();
|
|
2277
|
+
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
2278
|
+
const permission = PermitUtils.getPermission(permit, true);
|
|
2279
|
+
const sealed = await tnSealOutputV2(this.ctHash, this.chainId, permission, thresholdNetworkUrl);
|
|
2280
|
+
return PermitUtils.unseal(permit, sealed);
|
|
2062
2281
|
}
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2282
|
+
/**
|
|
2283
|
+
* Final step of the decryption process. MUST BE CALLED LAST IN THE CHAIN.
|
|
2284
|
+
*
|
|
2285
|
+
* This will:
|
|
2286
|
+
* - Use a permit based on provided permit OR chainId + account + permitHash
|
|
2287
|
+
* - Check permit validity
|
|
2288
|
+
* - Call CoFHE `/sealoutput` with the permit, which returns a sealed (encrypted) item
|
|
2289
|
+
* - Unseal the sealed item with the permit
|
|
2290
|
+
* - Return the unsealed item
|
|
2291
|
+
*
|
|
2292
|
+
* Example:
|
|
2293
|
+
* ```typescript
|
|
2294
|
+
* const unsealed = await decryptHandle(ctHash, utype)
|
|
2295
|
+
* .setChainId(11155111) // optional
|
|
2296
|
+
* .setAccount('0x123...890') // optional
|
|
2297
|
+
* .decrypt(); // execute
|
|
2298
|
+
* ```
|
|
2299
|
+
*
|
|
2300
|
+
* @returns The unsealed item.
|
|
2301
|
+
*/
|
|
2302
|
+
async decrypt() {
|
|
2303
|
+
this.validateUtypeOrThrow();
|
|
2304
|
+
const permit = await this.getResolvedPermit();
|
|
2305
|
+
PermitUtils.validate(permit);
|
|
2306
|
+
PermitUtils.isValid(permit);
|
|
2307
|
+
const chainId = permit._signedDomain.chainId;
|
|
2308
|
+
let unsealed;
|
|
2309
|
+
if (chainId === hardhat$1.id) {
|
|
2310
|
+
unsealed = await this.mocksSealOutput(permit);
|
|
2311
|
+
} else {
|
|
2312
|
+
unsealed = await this.productionSealOutput(permit);
|
|
2313
|
+
}
|
|
2314
|
+
return convertViaUtype(this.utype, unsealed);
|
|
2068
2315
|
}
|
|
2069
|
-
keysStorage?.setCrs(chainId, crs_data);
|
|
2070
|
-
return [crs_data, true];
|
|
2071
|
-
};
|
|
2072
|
-
var fetchKeys = async (config, chainId, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
|
|
2073
|
-
const coFheUrl = getCoFheUrlOrThrow(config, chainId);
|
|
2074
|
-
return await Promise.all([
|
|
2075
|
-
fetchFhePublicKey(coFheUrl, chainId, securityZone, tfhePublicKeyDeserializer, keysStorage),
|
|
2076
|
-
fetchCrs(coFheUrl, chainId, securityZone, compactPkeCrsDeserializer, keysStorage)
|
|
2077
|
-
]);
|
|
2078
|
-
};
|
|
2079
|
-
var fetchMultichainKeys = async (config, securityZone = 0, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage) => {
|
|
2080
|
-
await Promise.all(
|
|
2081
|
-
config.supportedChains.filter((chain) => chain.id !== hardhat.id).map(
|
|
2082
|
-
(chain) => fetchKeys(config, chain.id, securityZone, tfhePublicKeyDeserializer, compactPkeCrsDeserializer, keysStorage)
|
|
2083
|
-
)
|
|
2084
|
-
);
|
|
2085
2316
|
};
|
|
2086
2317
|
|
|
2087
2318
|
// core/client.ts
|
|
2319
|
+
var InitialConnectStore = {
|
|
2320
|
+
connected: false,
|
|
2321
|
+
connecting: false,
|
|
2322
|
+
connectError: void 0,
|
|
2323
|
+
chainId: void 0,
|
|
2324
|
+
account: void 0,
|
|
2325
|
+
publicClient: void 0,
|
|
2326
|
+
walletClient: void 0
|
|
2327
|
+
};
|
|
2088
2328
|
function createCofhesdkClientBase(opts) {
|
|
2089
2329
|
const keysStorage = createKeysStore(opts.config.fheKeyStorage);
|
|
2090
|
-
|
|
2091
|
-
let _walletClient = void 0;
|
|
2092
|
-
const connectStore = createStore(() => ({
|
|
2093
|
-
connected: false,
|
|
2094
|
-
connecting: false,
|
|
2095
|
-
connectError: void 0,
|
|
2096
|
-
chainId: void 0,
|
|
2097
|
-
account: void 0
|
|
2098
|
-
}));
|
|
2330
|
+
const connectStore = createStore(() => InitialConnectStore);
|
|
2099
2331
|
const updateConnectState = (partial) => {
|
|
2100
2332
|
connectStore.setState((state) => ({ ...state, ...partial }));
|
|
2101
2333
|
};
|
|
2102
|
-
let _connectPromise = void 0;
|
|
2103
2334
|
const _requireConnected = () => {
|
|
2104
2335
|
const state = connectStore.getState();
|
|
2105
|
-
const notConnected = !state.connected || !
|
|
2336
|
+
const notConnected = !state.connected || !state.account || !state.chainId || !state.publicClient || !state.walletClient;
|
|
2106
2337
|
if (notConnected) {
|
|
2107
2338
|
throw new CofhesdkError({
|
|
2108
2339
|
code: "NOT_CONNECTED" /* NotConnected */,
|
|
@@ -2112,55 +2343,39 @@ function createCofhesdkClientBase(opts) {
|
|
|
2112
2343
|
connected: state.connected,
|
|
2113
2344
|
account: state.account,
|
|
2114
2345
|
chainId: state.chainId,
|
|
2115
|
-
publicClient:
|
|
2116
|
-
walletClient:
|
|
2346
|
+
publicClient: state.publicClient,
|
|
2347
|
+
walletClient: state.walletClient
|
|
2117
2348
|
}
|
|
2118
2349
|
});
|
|
2119
2350
|
}
|
|
2120
2351
|
};
|
|
2121
|
-
const keyFetchResult = resultWrapper(async () => {
|
|
2122
|
-
if (opts.config.fheKeysPrefetching === "SUPPORTED_CHAINS") {
|
|
2123
|
-
await fetchMultichainKeys(
|
|
2124
|
-
opts.config,
|
|
2125
|
-
0,
|
|
2126
|
-
opts.tfhePublicKeyDeserializer,
|
|
2127
|
-
opts.compactPkeCrsDeserializer,
|
|
2128
|
-
keysStorage
|
|
2129
|
-
);
|
|
2130
|
-
return true;
|
|
2131
|
-
}
|
|
2132
|
-
return false;
|
|
2133
|
-
});
|
|
2134
2352
|
async function connect(publicClient, walletClient) {
|
|
2135
2353
|
const state = connectStore.getState();
|
|
2136
|
-
if (state.connected &&
|
|
2137
|
-
return
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2354
|
+
if (state.connected && state.publicClient === publicClient && state.walletClient === walletClient)
|
|
2355
|
+
return;
|
|
2356
|
+
updateConnectState({
|
|
2357
|
+
...InitialConnectStore,
|
|
2358
|
+
connecting: true
|
|
2359
|
+
});
|
|
2360
|
+
try {
|
|
2361
|
+
const chainId = await getPublicClientChainID(publicClient);
|
|
2362
|
+
const account = await getWalletClientAccount(walletClient);
|
|
2363
|
+
updateConnectState({
|
|
2364
|
+
connected: true,
|
|
2365
|
+
connecting: false,
|
|
2366
|
+
connectError: void 0,
|
|
2367
|
+
chainId,
|
|
2368
|
+
account,
|
|
2369
|
+
publicClient,
|
|
2370
|
+
walletClient
|
|
2371
|
+
});
|
|
2372
|
+
} catch (e) {
|
|
2373
|
+
updateConnectState({
|
|
2374
|
+
...InitialConnectStore,
|
|
2375
|
+
connectError: e
|
|
2376
|
+
});
|
|
2377
|
+
throw e;
|
|
2141
2378
|
}
|
|
2142
|
-
updateConnectState({ connecting: true, connectError: null, connected: false });
|
|
2143
|
-
_connectPromise = resultWrapper(
|
|
2144
|
-
// try
|
|
2145
|
-
async () => {
|
|
2146
|
-
_publicClient = publicClient;
|
|
2147
|
-
_walletClient = walletClient;
|
|
2148
|
-
const chainId = await getPublicClientChainID(publicClient);
|
|
2149
|
-
const account = await getWalletClientAccount(walletClient);
|
|
2150
|
-
updateConnectState({ connecting: false, connected: true, chainId, account });
|
|
2151
|
-
return true;
|
|
2152
|
-
},
|
|
2153
|
-
// catch
|
|
2154
|
-
(e) => {
|
|
2155
|
-
updateConnectState({ connecting: false, connected: false, connectError: e });
|
|
2156
|
-
return false;
|
|
2157
|
-
},
|
|
2158
|
-
// finally
|
|
2159
|
-
() => {
|
|
2160
|
-
_connectPromise = void 0;
|
|
2161
|
-
}
|
|
2162
|
-
);
|
|
2163
|
-
return _connectPromise;
|
|
2164
2379
|
}
|
|
2165
2380
|
function encryptInputs(inputs) {
|
|
2166
2381
|
const state = connectStore.getState();
|
|
@@ -2169,13 +2384,14 @@ function createCofhesdkClientBase(opts) {
|
|
|
2169
2384
|
account: state.account ?? void 0,
|
|
2170
2385
|
chainId: state.chainId ?? void 0,
|
|
2171
2386
|
config: opts.config,
|
|
2172
|
-
publicClient:
|
|
2173
|
-
walletClient:
|
|
2387
|
+
publicClient: state.publicClient ?? void 0,
|
|
2388
|
+
walletClient: state.walletClient ?? void 0,
|
|
2174
2389
|
zkvWalletClient: opts.config._internal?.zkvWalletClient,
|
|
2175
2390
|
tfhePublicKeyDeserializer: opts.tfhePublicKeyDeserializer,
|
|
2176
2391
|
compactPkeCrsDeserializer: opts.compactPkeCrsDeserializer,
|
|
2177
2392
|
zkBuilderAndCrsGenerator: opts.zkBuilderAndCrsGenerator,
|
|
2178
2393
|
initTfhe: opts.initTfhe,
|
|
2394
|
+
zkProveWorkerFn: opts.zkProveWorkerFn,
|
|
2179
2395
|
keysStorage,
|
|
2180
2396
|
requireConnected: _requireConnected
|
|
2181
2397
|
});
|
|
@@ -2188,8 +2404,8 @@ function createCofhesdkClientBase(opts) {
|
|
|
2188
2404
|
chainId: state.chainId ?? void 0,
|
|
2189
2405
|
account: state.account ?? void 0,
|
|
2190
2406
|
config: opts.config,
|
|
2191
|
-
publicClient:
|
|
2192
|
-
walletClient:
|
|
2407
|
+
publicClient: state.publicClient ?? void 0,
|
|
2408
|
+
walletClient: state.walletClient ?? void 0,
|
|
2193
2409
|
requireConnected: _requireConnected
|
|
2194
2410
|
});
|
|
2195
2411
|
}
|
|
@@ -2215,48 +2431,64 @@ function createCofhesdkClientBase(opts) {
|
|
|
2215
2431
|
getSnapshot: permits.getSnapshot,
|
|
2216
2432
|
subscribe: permits.subscribe,
|
|
2217
2433
|
// Creation methods (require connection)
|
|
2218
|
-
createSelf: async (options
|
|
2434
|
+
createSelf: async (options, clients) => {
|
|
2435
|
+
_requireConnected();
|
|
2436
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
2437
|
+
return permits.createSelf(options, publicClient, walletClient);
|
|
2438
|
+
},
|
|
2439
|
+
createSharing: async (options, clients) => {
|
|
2440
|
+
_requireConnected();
|
|
2441
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
2442
|
+
return permits.createSharing(options, publicClient, walletClient);
|
|
2443
|
+
},
|
|
2444
|
+
importShared: async (options, clients) => {
|
|
2219
2445
|
_requireConnected();
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2446
|
+
const { publicClient, walletClient } = clients ?? connectStore.getState();
|
|
2447
|
+
return permits.importShared(options, publicClient, walletClient);
|
|
2448
|
+
},
|
|
2449
|
+
// Get or create methods (require connection)
|
|
2450
|
+
getOrCreateSelfPermit: async (chainId, account, options) => {
|
|
2223
2451
|
_requireConnected();
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2452
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2453
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
2454
|
+
return permits.getOrCreateSelfPermit(publicClient, walletClient, _chainId, _account, options);
|
|
2455
|
+
},
|
|
2456
|
+
getOrCreateSharingPermit: async (options, chainId, account) => {
|
|
2227
2457
|
_requireConnected();
|
|
2228
|
-
|
|
2229
|
-
|
|
2458
|
+
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2459
|
+
const { publicClient, walletClient } = connectStore.getState();
|
|
2460
|
+
return permits.getOrCreateSharingPermit(publicClient, walletClient, options, _chainId, _account);
|
|
2461
|
+
},
|
|
2230
2462
|
// Retrieval methods (auto-fill chainId/account)
|
|
2231
|
-
getPermit: async (hash, chainId, account) =>
|
|
2463
|
+
getPermit: async (hash, chainId, account) => {
|
|
2232
2464
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2233
2465
|
return permits.getPermit(_chainId, _account, hash);
|
|
2234
|
-
}
|
|
2235
|
-
getPermits: async (chainId, account) =>
|
|
2466
|
+
},
|
|
2467
|
+
getPermits: async (chainId, account) => {
|
|
2236
2468
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2237
2469
|
return permits.getPermits(_chainId, _account);
|
|
2238
|
-
}
|
|
2239
|
-
getActivePermit: async (chainId, account) =>
|
|
2470
|
+
},
|
|
2471
|
+
getActivePermit: async (chainId, account) => {
|
|
2240
2472
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2241
2473
|
return permits.getActivePermit(_chainId, _account);
|
|
2242
|
-
}
|
|
2243
|
-
getActivePermitHash: async (chainId, account) =>
|
|
2474
|
+
},
|
|
2475
|
+
getActivePermitHash: async (chainId, account) => {
|
|
2244
2476
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2245
2477
|
return permits.getActivePermitHash(_chainId, _account);
|
|
2246
|
-
}
|
|
2478
|
+
},
|
|
2247
2479
|
// Mutation methods (auto-fill chainId/account)
|
|
2248
|
-
selectActivePermit:
|
|
2480
|
+
selectActivePermit: (hash, chainId, account) => {
|
|
2249
2481
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2250
2482
|
return permits.selectActivePermit(_chainId, _account, hash);
|
|
2251
|
-
}
|
|
2252
|
-
removePermit: async (hash, chainId, account
|
|
2483
|
+
},
|
|
2484
|
+
removePermit: async (hash, chainId, account, force) => {
|
|
2253
2485
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2254
|
-
return permits.removePermit(_chainId, _account, hash);
|
|
2255
|
-
}
|
|
2256
|
-
removeActivePermit: async (chainId, account) =>
|
|
2486
|
+
return permits.removePermit(_chainId, _account, hash, force);
|
|
2487
|
+
},
|
|
2488
|
+
removeActivePermit: async (chainId, account) => {
|
|
2257
2489
|
const { chainId: _chainId, account: _account } = _getChainIdAndAccount(chainId, account);
|
|
2258
2490
|
return permits.removeActivePermit(_chainId, _account);
|
|
2259
|
-
}
|
|
2491
|
+
},
|
|
2260
2492
|
// Utils (no context needed)
|
|
2261
2493
|
getHash: permits.getHash,
|
|
2262
2494
|
serialize: permits.serialize,
|
|
@@ -2266,10 +2498,6 @@ function createCofhesdkClientBase(opts) {
|
|
|
2266
2498
|
// Zustand reactive accessors (don't export store directly to prevent mutation)
|
|
2267
2499
|
getSnapshot: connectStore.getState,
|
|
2268
2500
|
subscribe: connectStore.subscribe,
|
|
2269
|
-
// initialization results
|
|
2270
|
-
initializationResults: {
|
|
2271
|
-
keyFetchResult
|
|
2272
|
-
},
|
|
2273
2501
|
// flags (read-only: reflect snapshot)
|
|
2274
2502
|
get connected() {
|
|
2275
2503
|
return connectStore.getState().connected;
|
|
@@ -2287,9 +2515,9 @@ function createCofhesdkClientBase(opts) {
|
|
|
2287
2515
|
// Example:
|
|
2288
2516
|
// async encryptData(data: unknown) {
|
|
2289
2517
|
// requireConnected();
|
|
2290
|
-
// // Use
|
|
2518
|
+
// // Use state.publicClient and state.walletClient for implementation
|
|
2291
2519
|
// },
|
|
2292
2520
|
};
|
|
2293
2521
|
}
|
|
2294
2522
|
|
|
2295
|
-
export { CofhesdkError, CofhesdkErrorCode, DecryptHandlesBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes,
|
|
2523
|
+
export { CofhesdkError, CofhesdkErrorCode, DecryptHandlesBuilder, EncryptInputsBuilder, EncryptStep, Encryptable, FheAllUTypes, FheTypes, FheUintUTypes, InitialConnectStore, MOCKS_ZK_VERIFIER_SIGNER_ADDRESS, assertCorrectEncryptedItemInput, createCofhesdkClientBase, createCofhesdkConfigBase, createKeysStore, fetchKeys, fheTypeToString, getCofhesdkConfigItem, isCofhesdkError, isEncryptableItem, isLastEncryptionStep, zkProveWithWorker };
|