@cofhe/sdk 0.4.0 → 0.5.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 +32 -0
- package/adapters/{ethers5.test.ts → test/ethers5.test.ts} +2 -2
- package/adapters/{ethers6.test.ts → test/ethers6.test.ts} +2 -2
- package/adapters/{hardhat.hh2.test.ts → test/hardhat.hh2.test.ts} +2 -2
- package/adapters/{index.test.ts → test/index.test.ts} +1 -1
- package/adapters/{wagmi.test.ts → test/wagmi.test.ts} +1 -1
- package/chains/{chains.test.ts → test/chains.test.ts} +1 -1
- package/core/client.ts +11 -1
- package/core/clientTypes.ts +3 -1
- package/core/consts.ts +9 -0
- package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
- package/core/decrypt/decryptForTxBuilder.ts +16 -2
- package/core/decrypt/decryptForViewBuilder.ts +14 -7
- package/core/decrypt/polling.ts +14 -0
- package/core/decrypt/tnDecryptV2.ts +250 -110
- package/core/decrypt/tnSealOutputV2.ts +245 -104
- package/core/decrypt/verifyDecryptResult.ts +65 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
- package/core/encrypt/zkPackProveVerify.ts +10 -19
- package/core/fetchKeys.ts +0 -2
- package/core/index.ts +9 -1
- package/core/keyStore.ts +5 -2
- package/core/permits.ts +5 -0
- package/core/{client.test.ts → test/client.test.ts} +7 -7
- package/core/{config.test.ts → test/config.test.ts} +1 -1
- package/core/test/decrypt.test.ts +252 -0
- package/core/test/decryptBuilders.test.ts +390 -0
- package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
- package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
- package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
- package/core/{permits.test.ts → test/permits.test.ts} +42 -1
- package/core/test/pollCallbacks.test.ts +563 -0
- package/core/types.ts +13 -0
- package/dist/chains.d.cts +2 -2
- package/dist/chains.d.ts +2 -2
- package/dist/chunk-4FP4V35O.js +13 -0
- package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
- package/dist/{chunk-MXND5SVN.js → chunk-S7OKGLFD.js} +485 -207
- package/dist/{clientTypes-kkrRdawm.d.ts → clientTypes-BSbwairE.d.cts} +23 -6
- package/dist/{clientTypes-ACVWbrXL.d.cts → clientTypes-DDmcgZ0a.d.ts} +23 -6
- package/dist/core.cjs +561 -244
- package/dist/core.d.cts +24 -6
- package/dist/core.d.ts +24 -6
- package/dist/core.js +3 -2
- package/dist/node.cjs +566 -246
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +14 -7
- package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.cts} +34 -4
- package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.ts} +34 -4
- package/dist/permits.cjs +66 -29
- package/dist/permits.d.cts +18 -13
- package/dist/permits.d.ts +18 -13
- package/dist/permits.js +2 -1
- package/dist/web.cjs +588 -251
- package/dist/web.d.cts +8 -4
- package/dist/web.d.ts +8 -4
- package/dist/web.js +34 -11
- package/dist/zkProve.worker.cjs +6 -3
- package/dist/zkProve.worker.js +5 -3
- package/node/index.ts +13 -4
- package/node/test/client.test.ts +25 -0
- package/node/test/config.test.ts +16 -0
- package/node/test/inherited.test.ts +244 -0
- package/node/test/tfheinit.test.ts +56 -0
- package/package.json +24 -22
- package/permits/permit.ts +31 -5
- package/permits/sealing.ts +1 -1
- package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
- package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
- package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
- package/permits/{store.test.ts → test/store.test.ts} +2 -2
- package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
- package/permits/types.ts +1 -1
- package/permits/validation.ts +42 -2
- package/web/const.ts +2 -0
- package/web/index.ts +20 -6
- package/web/storage.ts +18 -3
- package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
- package/web/test/config.web.test.ts +16 -0
- package/web/test/inherited.web.test.ts +245 -0
- package/web/test/tfheinit.web.test.ts +62 -0
- package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
- package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
- package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
- package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
- package/web/zkProve.worker.ts +4 -3
- package/node/client.test.ts +0 -147
- package/node/config.test.ts +0 -68
- package/node/encryptInputs.test.ts +0 -155
- package/web/config.web.test.ts +0 -69
- package/web/encryptInputs.web.test.ts +0 -172
- package/web/worker.builder.web.test.ts +0 -148
- /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
- /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
package/dist/web.cjs
CHANGED
|
@@ -14,25 +14,7 @@ var init = require('tfhe');
|
|
|
14
14
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
15
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
if (e && e.__esModule) return e;
|
|
19
|
-
var n = Object.create(null);
|
|
20
|
-
if (e) {
|
|
21
|
-
Object.keys(e).forEach(function (k) {
|
|
22
|
-
if (k !== 'default') {
|
|
23
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
24
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
25
|
-
enumerable: true,
|
|
26
|
-
get: function () { return e[k]; }
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
n.default = e;
|
|
32
|
-
return Object.freeze(n);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
var nacl__namespace = /*#__PURE__*/_interopNamespace(nacl);
|
|
17
|
+
var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
36
18
|
var init__default = /*#__PURE__*/_interopDefault(init);
|
|
37
19
|
|
|
38
20
|
// core/client.ts
|
|
@@ -126,6 +108,16 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
126
108
|
};
|
|
127
109
|
var isCofheError = (error) => error instanceof CofheError;
|
|
128
110
|
|
|
111
|
+
// core/consts.ts
|
|
112
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
113
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
114
|
+
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
115
|
+
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
116
|
+
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
117
|
+
var TFHE_RS_ZK_MAX_BITS = 2048;
|
|
118
|
+
var TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = BigInt(1 << 30);
|
|
119
|
+
var TFHE_RS_KEY_VERSION = 2;
|
|
120
|
+
|
|
129
121
|
// core/types.ts
|
|
130
122
|
var FheUintUTypes = [
|
|
131
123
|
2 /* Uint8 */,
|
|
@@ -248,7 +240,6 @@ var MAX_UINT32 = 4294967295n;
|
|
|
248
240
|
var MAX_UINT64 = 18446744073709551615n;
|
|
249
241
|
var MAX_UINT128 = 340282366920938463463374607431768211455n;
|
|
250
242
|
var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
|
|
251
|
-
var MAX_ENCRYPTABLE_BITS = 2048;
|
|
252
243
|
var zkPack = (items, builder) => {
|
|
253
244
|
let totalBits = 0;
|
|
254
245
|
for (const item of items) {
|
|
@@ -312,14 +303,14 @@ var zkPack = (items, builder) => {
|
|
|
312
303
|
}
|
|
313
304
|
}
|
|
314
305
|
}
|
|
315
|
-
if (totalBits >
|
|
306
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
316
307
|
throw new CofheError({
|
|
317
308
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
318
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
319
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
309
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
310
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
320
311
|
context: {
|
|
321
312
|
totalBits,
|
|
322
|
-
maxBits:
|
|
313
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
323
314
|
items
|
|
324
315
|
}
|
|
325
316
|
});
|
|
@@ -338,7 +329,7 @@ var zkProve = async (builder, crs, metadata) => {
|
|
|
338
329
|
1
|
|
339
330
|
// ZkComputeLoad.Verify
|
|
340
331
|
);
|
|
341
|
-
resolve(compactList.
|
|
332
|
+
resolve(compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT));
|
|
342
333
|
}, 0);
|
|
343
334
|
});
|
|
344
335
|
};
|
|
@@ -514,15 +505,6 @@ var MockZkVerifierAbi = [
|
|
|
514
505
|
},
|
|
515
506
|
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
516
507
|
];
|
|
517
|
-
|
|
518
|
-
// core/consts.ts
|
|
519
|
-
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
520
|
-
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
521
|
-
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
522
|
-
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
523
|
-
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
524
|
-
|
|
525
|
-
// core/encrypt/cofheMocksZkVerifySign.ts
|
|
526
508
|
function createMockZkVerifierSigner() {
|
|
527
509
|
return viem.createWalletClient({
|
|
528
510
|
chain: chains.hardhat,
|
|
@@ -564,14 +546,14 @@ async function cofheMocksCheckEncryptableBits(items) {
|
|
|
564
546
|
}
|
|
565
547
|
}
|
|
566
548
|
}
|
|
567
|
-
if (totalBits >
|
|
549
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
568
550
|
throw new CofheError({
|
|
569
551
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
570
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
571
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
552
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
553
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
572
554
|
context: {
|
|
573
555
|
totalBits,
|
|
574
|
-
maxBits:
|
|
556
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
575
557
|
items
|
|
576
558
|
}
|
|
577
559
|
});
|
|
@@ -842,6 +824,7 @@ function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
|
842
824
|
}
|
|
843
825
|
return url;
|
|
844
826
|
}
|
|
827
|
+
var KEYSTORE_NAME = `cofhesdk-keys-v${TFHE_RS_KEY_VERSION}`;
|
|
845
828
|
function isValidPersistedState(state) {
|
|
846
829
|
if (state && typeof state === "object") {
|
|
847
830
|
if ("fhe" in state && "crs" in state) {
|
|
@@ -896,7 +879,7 @@ function createKeysStore(storage) {
|
|
|
896
879
|
};
|
|
897
880
|
const clearKeysStorage = async () => {
|
|
898
881
|
if (storage) {
|
|
899
|
-
await storage.removeItem(
|
|
882
|
+
await storage.removeItem(KEYSTORE_NAME);
|
|
900
883
|
}
|
|
901
884
|
};
|
|
902
885
|
const rehydrateKeysStore = async () => {
|
|
@@ -926,7 +909,7 @@ function createStoreWithPersit(storage) {
|
|
|
926
909
|
if (_error)
|
|
927
910
|
throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
|
|
928
911
|
},
|
|
929
|
-
name:
|
|
912
|
+
name: KEYSTORE_NAME,
|
|
930
913
|
storage: middleware.createJSONStorage(() => storage),
|
|
931
914
|
merge: (persistedState, currentState) => {
|
|
932
915
|
const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
|
|
@@ -1651,7 +1634,7 @@ var SealingKey = class _SealingKey {
|
|
|
1651
1634
|
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
1652
1635
|
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
1653
1636
|
const privateKeyBytes = fromHexString(this.privateKey);
|
|
1654
|
-
const decryptedMessage =
|
|
1637
|
+
const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
|
|
1655
1638
|
if (!decryptedMessage) {
|
|
1656
1639
|
throw new Error("Failed to decrypt message");
|
|
1657
1640
|
}
|
|
@@ -1684,9 +1667,9 @@ var SealingKey = class _SealingKey {
|
|
|
1684
1667
|
static seal = (value, publicKey) => {
|
|
1685
1668
|
isString(publicKey);
|
|
1686
1669
|
isBigIntOrNumber(value);
|
|
1687
|
-
const ephemeralKeyPair =
|
|
1688
|
-
const nonce =
|
|
1689
|
-
const encryptedMessage =
|
|
1670
|
+
const ephemeralKeyPair = nacl__default.default.box.keyPair();
|
|
1671
|
+
const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
|
|
1672
|
+
const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
1690
1673
|
return {
|
|
1691
1674
|
data: encryptedMessage,
|
|
1692
1675
|
public_key: ephemeralKeyPair.publicKey,
|
|
@@ -1695,7 +1678,7 @@ var SealingKey = class _SealingKey {
|
|
|
1695
1678
|
};
|
|
1696
1679
|
};
|
|
1697
1680
|
var GenerateSealingKey = () => {
|
|
1698
|
-
const sodiumKeypair =
|
|
1681
|
+
const sodiumKeypair = nacl__default.default.box.keyPair();
|
|
1699
1682
|
return new SealingKey(toHexString2(sodiumKeypair.secretKey), toHexString2(sodiumKeypair.publicKey));
|
|
1700
1683
|
};
|
|
1701
1684
|
var SerializedSealingPair = zod.z.object({
|
|
@@ -1853,9 +1836,9 @@ var ValidationUtils = {
|
|
|
1853
1836
|
return false;
|
|
1854
1837
|
},
|
|
1855
1838
|
/**
|
|
1856
|
-
*
|
|
1839
|
+
* Checks that a permit is signed and not expired.
|
|
1857
1840
|
*/
|
|
1858
|
-
|
|
1841
|
+
isSignedAndNotExpired: (permit) => {
|
|
1859
1842
|
if (ValidationUtils.isExpired(permit)) {
|
|
1860
1843
|
return { valid: false, error: "expired" };
|
|
1861
1844
|
}
|
|
@@ -1863,6 +1846,34 @@ var ValidationUtils = {
|
|
|
1863
1846
|
return { valid: false, error: "not-signed" };
|
|
1864
1847
|
}
|
|
1865
1848
|
return { valid: true, error: null };
|
|
1849
|
+
},
|
|
1850
|
+
/**
|
|
1851
|
+
* Asserts that a permit is signed and not expired.
|
|
1852
|
+
*
|
|
1853
|
+
* Throws `Error` with message:
|
|
1854
|
+
* - `Permit is expired`
|
|
1855
|
+
* - `Permit is not signed`
|
|
1856
|
+
*/
|
|
1857
|
+
assertSignedAndNotExpired: (permit) => {
|
|
1858
|
+
const result = ValidationUtils.isSignedAndNotExpired(permit);
|
|
1859
|
+
if (result.valid)
|
|
1860
|
+
return;
|
|
1861
|
+
if (result.error === "expired") {
|
|
1862
|
+
throw new Error("Permit is expired");
|
|
1863
|
+
}
|
|
1864
|
+
if (result.error === "not-signed") {
|
|
1865
|
+
throw new Error("Permit is not signed");
|
|
1866
|
+
}
|
|
1867
|
+
throw new Error("Permit is invalid");
|
|
1868
|
+
},
|
|
1869
|
+
isValid: (permit) => {
|
|
1870
|
+
const schema = permit.type === "self" ? SelfPermitValidator : permit.type === "sharing" ? SharingPermitValidator : permit.type === "recipient" ? ImportPermitValidator : null;
|
|
1871
|
+
if (schema == null)
|
|
1872
|
+
return { valid: false, error: "invalid-schema" };
|
|
1873
|
+
const schemaResult = schema.safeParse(permit);
|
|
1874
|
+
if (!schemaResult.success)
|
|
1875
|
+
return { valid: false, error: "invalid-schema" };
|
|
1876
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
1866
1877
|
}
|
|
1867
1878
|
};
|
|
1868
1879
|
|
|
@@ -2244,9 +2255,9 @@ var PermitUtils = {
|
|
|
2244
2255
|
};
|
|
2245
2256
|
},
|
|
2246
2257
|
/**
|
|
2247
|
-
* Validate a permit
|
|
2258
|
+
* Validate a permit (schema-level validation)
|
|
2248
2259
|
*/
|
|
2249
|
-
|
|
2260
|
+
validateSchema: (permit) => {
|
|
2250
2261
|
if (permit.type === "self") {
|
|
2251
2262
|
return validateSelfPermit(permit);
|
|
2252
2263
|
} else if (permit.type === "sharing") {
|
|
@@ -2257,12 +2268,27 @@ var PermitUtils = {
|
|
|
2257
2268
|
throw new Error("Invalid permit type");
|
|
2258
2269
|
}
|
|
2259
2270
|
},
|
|
2271
|
+
/**
|
|
2272
|
+
* Validate a permit (holistic validation).
|
|
2273
|
+
*
|
|
2274
|
+
* This validates:
|
|
2275
|
+
* - Permit schema (shape + invariants)
|
|
2276
|
+
* - Permit is signed
|
|
2277
|
+
* - Permit is not expired
|
|
2278
|
+
*
|
|
2279
|
+
* For schema-only validation, use `validateSchema(permit)`.
|
|
2280
|
+
*/
|
|
2281
|
+
validate: (permit) => {
|
|
2282
|
+
const validated = PermitUtils.validateSchema(permit);
|
|
2283
|
+
ValidationUtils.assertSignedAndNotExpired(validated);
|
|
2284
|
+
return validated;
|
|
2285
|
+
},
|
|
2260
2286
|
/**
|
|
2261
2287
|
* Get the permission object from a permit (for use in contracts)
|
|
2262
2288
|
*/
|
|
2263
2289
|
getPermission: (permit, skipValidation = false) => {
|
|
2264
2290
|
if (!skipValidation) {
|
|
2265
|
-
PermitUtils.
|
|
2291
|
+
PermitUtils.validateSchema(permit);
|
|
2266
2292
|
}
|
|
2267
2293
|
return {
|
|
2268
2294
|
issuer: permit.issuer,
|
|
@@ -2328,8 +2354,17 @@ var PermitUtils = {
|
|
|
2328
2354
|
return ValidationUtils.isSigned(permit);
|
|
2329
2355
|
},
|
|
2330
2356
|
/**
|
|
2331
|
-
* Check if permit is
|
|
2357
|
+
* Check if permit is signed and not expired
|
|
2332
2358
|
*/
|
|
2359
|
+
isSignedAndNotExpired: (permit) => {
|
|
2360
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
2361
|
+
},
|
|
2362
|
+
/**
|
|
2363
|
+
* Assert that permit is signed and not expired
|
|
2364
|
+
*/
|
|
2365
|
+
assertSignedAndNotExpired: (permit) => {
|
|
2366
|
+
return ValidationUtils.assertSignedAndNotExpired(permit);
|
|
2367
|
+
},
|
|
2333
2368
|
isValid: (permit) => {
|
|
2334
2369
|
return ValidationUtils.isValid(permit);
|
|
2335
2370
|
},
|
|
@@ -2507,6 +2542,9 @@ var importShared = async (options, publicClient, walletClient) => {
|
|
|
2507
2542
|
var getHash = (permit) => {
|
|
2508
2543
|
return PermitUtils.getHash(permit);
|
|
2509
2544
|
};
|
|
2545
|
+
var exportShared = (permit) => {
|
|
2546
|
+
return PermitUtils.export(permit);
|
|
2547
|
+
};
|
|
2510
2548
|
var serialize = (permit) => {
|
|
2511
2549
|
return PermitUtils.serialize(permit);
|
|
2512
2550
|
};
|
|
@@ -2557,6 +2595,7 @@ var permits = {
|
|
|
2557
2595
|
getOrCreateSelfPermit,
|
|
2558
2596
|
getOrCreateSharingPermit,
|
|
2559
2597
|
getHash,
|
|
2598
|
+
export: exportShared,
|
|
2560
2599
|
serialize,
|
|
2561
2600
|
deserialize,
|
|
2562
2601
|
getPermit: getPermit2,
|
|
@@ -2799,9 +2838,19 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
|
|
|
2799
2838
|
return unsealed;
|
|
2800
2839
|
}
|
|
2801
2840
|
|
|
2841
|
+
// core/decrypt/polling.ts
|
|
2842
|
+
function computeMinuteRampPollIntervalMs(elapsedMs, params) {
|
|
2843
|
+
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
|
2844
|
+
const intervalSeconds = 1 + Math.floor(elapsedSeconds / 60);
|
|
2845
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
2846
|
+
return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2802
2849
|
// core/decrypt/tnSealOutputV2.ts
|
|
2803
2850
|
var POLL_INTERVAL_MS = 1e3;
|
|
2804
|
-
var
|
|
2851
|
+
var POLL_MAX_INTERVAL_MS = 1e4;
|
|
2852
|
+
var SEAL_OUTPUT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2853
|
+
var SUBMIT_RETRY_INTERVAL_MS = 1e3;
|
|
2805
2854
|
function numberArrayToUint8Array(arr) {
|
|
2806
2855
|
return new Uint8Array(arr);
|
|
2807
2856
|
}
|
|
@@ -2818,93 +2867,193 @@ function convertSealedData(sealed) {
|
|
|
2818
2867
|
nonce: numberArrayToUint8Array(sealed.nonce)
|
|
2819
2868
|
};
|
|
2820
2869
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
method: "POST",
|
|
2831
|
-
headers: {
|
|
2832
|
-
"Content-Type": "application/json"
|
|
2833
|
-
},
|
|
2834
|
-
body: JSON.stringify(body)
|
|
2835
|
-
});
|
|
2836
|
-
} catch (e) {
|
|
2837
|
-
throw new CofheError({
|
|
2838
|
-
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2839
|
-
message: `sealOutput request failed`,
|
|
2840
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2841
|
-
cause: e instanceof Error ? e : void 0,
|
|
2842
|
-
context: {
|
|
2843
|
-
thresholdNetworkUrl,
|
|
2844
|
-
body
|
|
2845
|
-
}
|
|
2846
|
-
});
|
|
2870
|
+
function getSealedDataFromSubmitResponse(value) {
|
|
2871
|
+
if (value.sealed)
|
|
2872
|
+
return value.sealed;
|
|
2873
|
+
if (Array.isArray(value.sealed_data) && Array.isArray(value.ephemeral_public_key) && Array.isArray(value.nonce)) {
|
|
2874
|
+
return {
|
|
2875
|
+
data: value.sealed_data,
|
|
2876
|
+
public_key: value.ephemeral_public_key,
|
|
2877
|
+
nonce: value.nonce
|
|
2878
|
+
};
|
|
2847
2879
|
}
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
errorMessage = response.statusText || errorMessage;
|
|
2855
|
-
}
|
|
2880
|
+
return void 0;
|
|
2881
|
+
}
|
|
2882
|
+
function parseCompletedSealOutputResponse(params) {
|
|
2883
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
2884
|
+
if (value.is_succeed === false) {
|
|
2885
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
2856
2886
|
throw new CofheError({
|
|
2857
2887
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2858
2888
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2859
|
-
hint: "Check the threshold network URL and request parameters.",
|
|
2860
2889
|
context: {
|
|
2861
2890
|
thresholdNetworkUrl,
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
body
|
|
2891
|
+
requestId,
|
|
2892
|
+
response: value
|
|
2865
2893
|
}
|
|
2866
2894
|
});
|
|
2867
2895
|
}
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
submitResponse = await response.json();
|
|
2871
|
-
} catch (e) {
|
|
2896
|
+
const sealed = "sealed" in value ? value.sealed : getSealedDataFromSubmitResponse(value);
|
|
2897
|
+
if (!sealed) {
|
|
2872
2898
|
throw new CofheError({
|
|
2873
|
-
code: "
|
|
2874
|
-
message: `
|
|
2875
|
-
cause: e instanceof Error ? e : void 0,
|
|
2899
|
+
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2900
|
+
message: `sealOutput request completed but returned no sealed data`,
|
|
2876
2901
|
context: {
|
|
2877
2902
|
thresholdNetworkUrl,
|
|
2878
|
-
|
|
2903
|
+
requestId,
|
|
2904
|
+
response: value
|
|
2879
2905
|
}
|
|
2880
2906
|
});
|
|
2881
2907
|
}
|
|
2882
|
-
|
|
2908
|
+
return convertSealedData(sealed);
|
|
2909
|
+
}
|
|
2910
|
+
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
2911
|
+
const body = {
|
|
2912
|
+
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
2913
|
+
host_chain_id: chainId,
|
|
2914
|
+
permit: permission
|
|
2915
|
+
};
|
|
2916
|
+
let attemptIndex = 0;
|
|
2917
|
+
for (; ; ) {
|
|
2918
|
+
let response;
|
|
2919
|
+
try {
|
|
2920
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
|
|
2921
|
+
method: "POST",
|
|
2922
|
+
headers: {
|
|
2923
|
+
"Content-Type": "application/json"
|
|
2924
|
+
},
|
|
2925
|
+
body: JSON.stringify(body)
|
|
2926
|
+
});
|
|
2927
|
+
} catch (e) {
|
|
2928
|
+
throw new CofheError({
|
|
2929
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2930
|
+
message: `sealOutput request failed`,
|
|
2931
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2932
|
+
cause: e instanceof Error ? e : void 0,
|
|
2933
|
+
context: {
|
|
2934
|
+
thresholdNetworkUrl,
|
|
2935
|
+
body,
|
|
2936
|
+
attemptIndex
|
|
2937
|
+
}
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2940
|
+
if (!response.ok) {
|
|
2941
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
2942
|
+
try {
|
|
2943
|
+
const errorBody = await response.json();
|
|
2944
|
+
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
2945
|
+
} catch {
|
|
2946
|
+
errorMessage = response.statusText || errorMessage;
|
|
2947
|
+
}
|
|
2948
|
+
throw new CofheError({
|
|
2949
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2950
|
+
message: `sealOutput request failed: ${errorMessage}`,
|
|
2951
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
2952
|
+
context: {
|
|
2953
|
+
thresholdNetworkUrl,
|
|
2954
|
+
status: response.status,
|
|
2955
|
+
statusText: response.statusText,
|
|
2956
|
+
body,
|
|
2957
|
+
attemptIndex
|
|
2958
|
+
}
|
|
2959
|
+
});
|
|
2960
|
+
}
|
|
2961
|
+
let submitResponse;
|
|
2962
|
+
if (response.status !== 204) {
|
|
2963
|
+
try {
|
|
2964
|
+
submitResponse = await response.json();
|
|
2965
|
+
} catch (e) {
|
|
2966
|
+
throw new CofheError({
|
|
2967
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2968
|
+
message: `Failed to parse sealOutput submit response`,
|
|
2969
|
+
cause: e instanceof Error ? e : void 0,
|
|
2970
|
+
context: {
|
|
2971
|
+
thresholdNetworkUrl,
|
|
2972
|
+
body,
|
|
2973
|
+
attemptIndex
|
|
2974
|
+
}
|
|
2975
|
+
});
|
|
2976
|
+
}
|
|
2977
|
+
if (getSealedDataFromSubmitResponse(submitResponse)) {
|
|
2978
|
+
return {
|
|
2979
|
+
kind: "completed",
|
|
2980
|
+
sealed: parseCompletedSealOutputResponse({
|
|
2981
|
+
value: submitResponse,
|
|
2982
|
+
thresholdNetworkUrl,
|
|
2983
|
+
requestId: submitResponse.request_id
|
|
2984
|
+
})
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
if (submitResponse.request_id) {
|
|
2988
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
if (response.status === 204) {
|
|
2992
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
2993
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
2994
|
+
throw new CofheError({
|
|
2995
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2996
|
+
message: `sealOutput submit retried without receiving request_id for ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
2997
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
2998
|
+
context: {
|
|
2999
|
+
thresholdNetworkUrl,
|
|
3000
|
+
body,
|
|
3001
|
+
attemptIndex,
|
|
3002
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
|
|
3003
|
+
submitResponse,
|
|
3004
|
+
status: response.status
|
|
3005
|
+
}
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
3008
|
+
onPoll?.({
|
|
3009
|
+
operation: "sealoutput",
|
|
3010
|
+
requestId: "",
|
|
3011
|
+
attemptIndex,
|
|
3012
|
+
elapsedMs,
|
|
3013
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS,
|
|
3014
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3015
|
+
});
|
|
3016
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS));
|
|
3017
|
+
attemptIndex += 1;
|
|
3018
|
+
continue;
|
|
3019
|
+
}
|
|
2883
3020
|
throw new CofheError({
|
|
2884
3021
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2885
3022
|
message: `sealOutput submit response missing request_id`,
|
|
2886
3023
|
context: {
|
|
2887
3024
|
thresholdNetworkUrl,
|
|
2888
3025
|
body,
|
|
2889
|
-
submitResponse
|
|
3026
|
+
submitResponse,
|
|
3027
|
+
attemptIndex
|
|
2890
3028
|
}
|
|
2891
3029
|
});
|
|
2892
3030
|
}
|
|
2893
|
-
return submitResponse.request_id;
|
|
2894
3031
|
}
|
|
2895
|
-
async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3032
|
+
async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
3033
|
+
let attemptIndex = 0;
|
|
3034
|
+
while (true) {
|
|
3035
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3036
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3037
|
+
minIntervalMs: POLL_INTERVAL_MS,
|
|
3038
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS
|
|
3039
|
+
});
|
|
3040
|
+
onPoll?.({
|
|
3041
|
+
operation: "sealoutput",
|
|
3042
|
+
requestId,
|
|
3043
|
+
attemptIndex,
|
|
3044
|
+
elapsedMs,
|
|
3045
|
+
intervalMs,
|
|
3046
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3047
|
+
});
|
|
3048
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
2900
3049
|
throw new CofheError({
|
|
2901
3050
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2902
|
-
message: `sealOutput polling timed out after ${
|
|
3051
|
+
message: `sealOutput polling timed out after ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
2903
3052
|
hint: "The request may still be processing. Try again later.",
|
|
2904
3053
|
context: {
|
|
2905
3054
|
thresholdNetworkUrl,
|
|
2906
3055
|
requestId,
|
|
2907
|
-
timeoutMs:
|
|
3056
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
2908
3057
|
}
|
|
2909
3058
|
});
|
|
2910
3059
|
}
|
|
@@ -2973,32 +3122,14 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2973
3122
|
});
|
|
2974
3123
|
}
|
|
2975
3124
|
if (statusResponse.status === "COMPLETED") {
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
context: {
|
|
2982
|
-
thresholdNetworkUrl,
|
|
2983
|
-
requestId,
|
|
2984
|
-
statusResponse
|
|
2985
|
-
}
|
|
2986
|
-
});
|
|
2987
|
-
}
|
|
2988
|
-
if (!statusResponse.sealed) {
|
|
2989
|
-
throw new CofheError({
|
|
2990
|
-
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2991
|
-
message: `sealOutput request completed but returned no sealed data`,
|
|
2992
|
-
context: {
|
|
2993
|
-
thresholdNetworkUrl,
|
|
2994
|
-
requestId,
|
|
2995
|
-
statusResponse
|
|
2996
|
-
}
|
|
2997
|
-
});
|
|
2998
|
-
}
|
|
2999
|
-
return convertSealedData(statusResponse.sealed);
|
|
3125
|
+
return parseCompletedSealOutputResponse({
|
|
3126
|
+
value: statusResponse,
|
|
3127
|
+
thresholdNetworkUrl,
|
|
3128
|
+
requestId
|
|
3129
|
+
});
|
|
3000
3130
|
}
|
|
3001
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3131
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3132
|
+
attemptIndex += 1;
|
|
3002
3133
|
}
|
|
3003
3134
|
throw new CofheError({
|
|
3004
3135
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
@@ -3009,9 +3140,21 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
3009
3140
|
}
|
|
3010
3141
|
});
|
|
3011
3142
|
}
|
|
3012
|
-
async function tnSealOutputV2(
|
|
3013
|
-
const
|
|
3014
|
-
|
|
3143
|
+
async function tnSealOutputV2(params) {
|
|
3144
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
3145
|
+
const overallStartTime = Date.now();
|
|
3146
|
+
const submitResult = await submitSealOutputRequest(
|
|
3147
|
+
thresholdNetworkUrl,
|
|
3148
|
+
ctHash,
|
|
3149
|
+
chainId,
|
|
3150
|
+
permission,
|
|
3151
|
+
overallStartTime,
|
|
3152
|
+
onPoll
|
|
3153
|
+
);
|
|
3154
|
+
if (submitResult.kind === "completed") {
|
|
3155
|
+
return submitResult.sealed;
|
|
3156
|
+
}
|
|
3157
|
+
return await pollSealOutputStatus(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
3015
3158
|
}
|
|
3016
3159
|
|
|
3017
3160
|
// core/decrypt/decryptForViewBuilder.ts
|
|
@@ -3020,6 +3163,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3020
3163
|
utype;
|
|
3021
3164
|
permitHash;
|
|
3022
3165
|
permit;
|
|
3166
|
+
pollCallback;
|
|
3023
3167
|
constructor(params) {
|
|
3024
3168
|
super({
|
|
3025
3169
|
config: params.config,
|
|
@@ -3076,6 +3220,10 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3076
3220
|
getAccount() {
|
|
3077
3221
|
return this.account;
|
|
3078
3222
|
}
|
|
3223
|
+
onPoll(callback) {
|
|
3224
|
+
this.pollCallback = callback;
|
|
3225
|
+
return this;
|
|
3226
|
+
}
|
|
3079
3227
|
withPermit(permitOrPermitHash) {
|
|
3080
3228
|
if (typeof permitOrPermitHash === "string") {
|
|
3081
3229
|
this.permitHash = permitOrPermitHash;
|
|
@@ -3199,7 +3347,13 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3199
3347
|
this.assertPublicClient();
|
|
3200
3348
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3201
3349
|
const permission = PermitUtils.getPermission(permit, true);
|
|
3202
|
-
const sealed = await tnSealOutputV2(
|
|
3350
|
+
const sealed = await tnSealOutputV2({
|
|
3351
|
+
ctHash: this.ctHash,
|
|
3352
|
+
chainId: this.chainId,
|
|
3353
|
+
permission,
|
|
3354
|
+
thresholdNetworkUrl,
|
|
3355
|
+
onPoll: this.pollCallback
|
|
3356
|
+
});
|
|
3203
3357
|
return PermitUtils.unseal(permit, sealed);
|
|
3204
3358
|
}
|
|
3205
3359
|
/**
|
|
@@ -3227,7 +3381,6 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3227
3381
|
this.validateUtypeOrThrow();
|
|
3228
3382
|
const permit = await this.getResolvedPermit();
|
|
3229
3383
|
PermitUtils.validate(permit);
|
|
3230
|
-
PermitUtils.isValid(permit);
|
|
3231
3384
|
const chainId = permit._signedDomain.chainId;
|
|
3232
3385
|
let unsealed;
|
|
3233
3386
|
if (chainId === hardhat2.id) {
|
|
@@ -3238,6 +3391,9 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3238
3391
|
return convertViaUtype(this.utype, unsealed);
|
|
3239
3392
|
}
|
|
3240
3393
|
};
|
|
3394
|
+
var UINT_TYPE_MASK = 0x7fn;
|
|
3395
|
+
var TYPE_BYTE_OFFSET = 8n;
|
|
3396
|
+
var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
|
|
3241
3397
|
async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
3242
3398
|
let allowed;
|
|
3243
3399
|
let error;
|
|
@@ -3275,7 +3431,13 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
|
3275
3431
|
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3276
3432
|
});
|
|
3277
3433
|
}
|
|
3278
|
-
const
|
|
3434
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
3435
|
+
const normalizedCtHash = BigInt(ctHash);
|
|
3436
|
+
const encryptionType = getEncryptionTypeFromCtHash(normalizedCtHash);
|
|
3437
|
+
const packed = viem.encodePacked(
|
|
3438
|
+
["uint256", "uint32", "uint64", "uint256"],
|
|
3439
|
+
[decryptedValue, encryptionType, BigInt(chainId), normalizedCtHash]
|
|
3440
|
+
);
|
|
3279
3441
|
const messageHash = viem.keccak256(packed);
|
|
3280
3442
|
const signature = await accounts.sign({
|
|
3281
3443
|
hash: messageHash,
|
|
@@ -3347,7 +3509,9 @@ function parseDecryptedBytesToBigInt(decrypted) {
|
|
|
3347
3509
|
|
|
3348
3510
|
// core/decrypt/tnDecryptV2.ts
|
|
3349
3511
|
var POLL_INTERVAL_MS2 = 1e3;
|
|
3350
|
-
var
|
|
3512
|
+
var POLL_MAX_INTERVAL_MS2 = 1e4;
|
|
3513
|
+
var DECRYPT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3514
|
+
var SUBMIT_RETRY_INTERVAL_MS2 = 1e3;
|
|
3351
3515
|
function assertDecryptSubmitResponseV2(value) {
|
|
3352
3516
|
if (value == null || typeof value !== "object") {
|
|
3353
3517
|
throw new CofheError({
|
|
@@ -3359,16 +3523,65 @@ function assertDecryptSubmitResponseV2(value) {
|
|
|
3359
3523
|
});
|
|
3360
3524
|
}
|
|
3361
3525
|
const v = value;
|
|
3362
|
-
if (
|
|
3526
|
+
if (v.request_id !== null && typeof v.request_id !== "string") {
|
|
3363
3527
|
throw new CofheError({
|
|
3364
3528
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3365
|
-
message: "decrypt submit response
|
|
3529
|
+
message: "decrypt submit response has invalid request_id",
|
|
3366
3530
|
context: {
|
|
3367
3531
|
value
|
|
3368
3532
|
}
|
|
3369
3533
|
});
|
|
3370
3534
|
}
|
|
3371
|
-
return {
|
|
3535
|
+
return {
|
|
3536
|
+
request_id: v.request_id ?? null,
|
|
3537
|
+
status: typeof v.status === "string" ? v.status : void 0,
|
|
3538
|
+
is_succeed: typeof v.is_succeed === "boolean" ? v.is_succeed : void 0,
|
|
3539
|
+
decrypted: Array.isArray(v.decrypted) ? v.decrypted : void 0,
|
|
3540
|
+
signature: typeof v.signature === "string" ? v.signature : void 0,
|
|
3541
|
+
encryption_type: typeof v.encryption_type === "number" ? v.encryption_type : void 0,
|
|
3542
|
+
error_message: typeof v.error_message === "string" || v.error_message === null ? v.error_message : void 0,
|
|
3543
|
+
message: typeof v.message === "string" ? v.message : void 0
|
|
3544
|
+
};
|
|
3545
|
+
}
|
|
3546
|
+
function parseCompletedDecryptResponseV2(params) {
|
|
3547
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
3548
|
+
if (value.is_succeed === false) {
|
|
3549
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
3550
|
+
throw new CofheError({
|
|
3551
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3552
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3553
|
+
context: {
|
|
3554
|
+
thresholdNetworkUrl,
|
|
3555
|
+
requestId,
|
|
3556
|
+
response: value
|
|
3557
|
+
}
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
if (value.error_message) {
|
|
3561
|
+
throw new CofheError({
|
|
3562
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3563
|
+
message: `decrypt request failed: ${value.error_message}`,
|
|
3564
|
+
context: {
|
|
3565
|
+
thresholdNetworkUrl,
|
|
3566
|
+
requestId,
|
|
3567
|
+
response: value
|
|
3568
|
+
}
|
|
3569
|
+
});
|
|
3570
|
+
}
|
|
3571
|
+
if (!Array.isArray(value.decrypted)) {
|
|
3572
|
+
throw new CofheError({
|
|
3573
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3574
|
+
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3575
|
+
context: {
|
|
3576
|
+
thresholdNetworkUrl,
|
|
3577
|
+
requestId,
|
|
3578
|
+
response: value
|
|
3579
|
+
}
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
const decryptedValue = parseDecryptedBytesToBigInt(value.decrypted);
|
|
3583
|
+
const signature = normalizeTnSignature(value.signature);
|
|
3584
|
+
return { decryptedValue, signature };
|
|
3372
3585
|
}
|
|
3373
3586
|
function assertDecryptStatusResponseV2(value) {
|
|
3374
3587
|
if (value == null || typeof value !== "object") {
|
|
@@ -3414,7 +3627,7 @@ function assertDecryptStatusResponseV2(value) {
|
|
|
3414
3627
|
}
|
|
3415
3628
|
return value;
|
|
3416
3629
|
}
|
|
3417
|
-
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission) {
|
|
3630
|
+
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
3418
3631
|
const body = {
|
|
3419
3632
|
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3420
3633
|
host_chain_id: chainId
|
|
@@ -3422,79 +3635,151 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
3422
3635
|
if (permission) {
|
|
3423
3636
|
body.permit = permission;
|
|
3424
3637
|
}
|
|
3425
|
-
let
|
|
3426
|
-
|
|
3427
|
-
response
|
|
3428
|
-
method: "POST",
|
|
3429
|
-
headers: {
|
|
3430
|
-
"Content-Type": "application/json"
|
|
3431
|
-
},
|
|
3432
|
-
body: JSON.stringify(body)
|
|
3433
|
-
});
|
|
3434
|
-
} catch (e) {
|
|
3435
|
-
throw new CofheError({
|
|
3436
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3437
|
-
message: `decrypt request failed`,
|
|
3438
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3439
|
-
cause: e instanceof Error ? e : void 0,
|
|
3440
|
-
context: {
|
|
3441
|
-
thresholdNetworkUrl,
|
|
3442
|
-
body
|
|
3443
|
-
}
|
|
3444
|
-
});
|
|
3445
|
-
}
|
|
3446
|
-
if (!response.ok) {
|
|
3447
|
-
let errorMessage = `HTTP ${response.status}`;
|
|
3638
|
+
let attemptIndex = 0;
|
|
3639
|
+
for (; ; ) {
|
|
3640
|
+
let response;
|
|
3448
3641
|
try {
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3642
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
|
|
3643
|
+
method: "POST",
|
|
3644
|
+
headers: {
|
|
3645
|
+
"Content-Type": "application/json"
|
|
3646
|
+
},
|
|
3647
|
+
body: JSON.stringify(body)
|
|
3648
|
+
});
|
|
3649
|
+
} catch (e) {
|
|
3650
|
+
throw new CofheError({
|
|
3651
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3652
|
+
message: `decrypt request failed`,
|
|
3653
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3654
|
+
cause: e instanceof Error ? e : void 0,
|
|
3655
|
+
context: {
|
|
3656
|
+
thresholdNetworkUrl,
|
|
3657
|
+
body,
|
|
3658
|
+
attemptIndex
|
|
3659
|
+
}
|
|
3660
|
+
});
|
|
3455
3661
|
}
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3662
|
+
if (!response.ok) {
|
|
3663
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
3664
|
+
try {
|
|
3665
|
+
const errorBody = await response.json();
|
|
3666
|
+
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
3667
|
+
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
3668
|
+
errorMessage = maybeMessage;
|
|
3669
|
+
} catch {
|
|
3670
|
+
errorMessage = response.statusText || errorMessage;
|
|
3465
3671
|
}
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3672
|
+
throw new CofheError({
|
|
3673
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3674
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3675
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3676
|
+
context: {
|
|
3677
|
+
thresholdNetworkUrl,
|
|
3678
|
+
status: response.status,
|
|
3679
|
+
statusText: response.statusText,
|
|
3680
|
+
body,
|
|
3681
|
+
attemptIndex
|
|
3682
|
+
}
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
let submitResponse;
|
|
3686
|
+
if (response.status !== 204) {
|
|
3687
|
+
let rawJson;
|
|
3688
|
+
try {
|
|
3689
|
+
rawJson = await response.json();
|
|
3690
|
+
} catch (e) {
|
|
3691
|
+
throw new CofheError({
|
|
3692
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3693
|
+
message: `Failed to parse decrypt submit response`,
|
|
3694
|
+
cause: e instanceof Error ? e : void 0,
|
|
3695
|
+
context: {
|
|
3696
|
+
thresholdNetworkUrl,
|
|
3697
|
+
body,
|
|
3698
|
+
attemptIndex
|
|
3699
|
+
}
|
|
3700
|
+
});
|
|
3701
|
+
}
|
|
3702
|
+
submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3703
|
+
if (Array.isArray(submitResponse.decrypted) && typeof submitResponse.signature === "string") {
|
|
3704
|
+
return {
|
|
3705
|
+
kind: "completed",
|
|
3706
|
+
...parseCompletedDecryptResponseV2({
|
|
3707
|
+
value: submitResponse,
|
|
3708
|
+
thresholdNetworkUrl,
|
|
3709
|
+
requestId: submitResponse.request_id
|
|
3710
|
+
})
|
|
3711
|
+
};
|
|
3712
|
+
}
|
|
3713
|
+
if (submitResponse.request_id) {
|
|
3714
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
if (response.status === 204) {
|
|
3718
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3719
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3720
|
+
throw new CofheError({
|
|
3721
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3722
|
+
message: `decrypt submit retried without receiving request_id for ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3723
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
3724
|
+
context: {
|
|
3725
|
+
thresholdNetworkUrl,
|
|
3726
|
+
body,
|
|
3727
|
+
attemptIndex,
|
|
3728
|
+
timeoutMs: DECRYPT_TIMEOUT_MS,
|
|
3729
|
+
submitResponse,
|
|
3730
|
+
status: response.status
|
|
3731
|
+
}
|
|
3732
|
+
});
|
|
3733
|
+
}
|
|
3734
|
+
onPoll?.({
|
|
3735
|
+
operation: "decrypt",
|
|
3736
|
+
requestId: "",
|
|
3737
|
+
attemptIndex,
|
|
3738
|
+
elapsedMs,
|
|
3739
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS2,
|
|
3740
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3741
|
+
});
|
|
3742
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS2));
|
|
3743
|
+
attemptIndex += 1;
|
|
3744
|
+
continue;
|
|
3745
|
+
}
|
|
3472
3746
|
throw new CofheError({
|
|
3473
3747
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3474
|
-
message: `
|
|
3475
|
-
cause: e instanceof Error ? e : void 0,
|
|
3748
|
+
message: `decrypt submit response missing request_id`,
|
|
3476
3749
|
context: {
|
|
3477
3750
|
thresholdNetworkUrl,
|
|
3478
|
-
body
|
|
3751
|
+
body,
|
|
3752
|
+
submitResponse,
|
|
3753
|
+
attemptIndex
|
|
3479
3754
|
}
|
|
3480
3755
|
});
|
|
3481
3756
|
}
|
|
3482
|
-
const submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3483
|
-
return submitResponse.request_id;
|
|
3484
3757
|
}
|
|
3485
|
-
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3758
|
+
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
3759
|
+
let attemptIndex = 0;
|
|
3760
|
+
while (true) {
|
|
3761
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3762
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3763
|
+
minIntervalMs: POLL_INTERVAL_MS2,
|
|
3764
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS2
|
|
3765
|
+
});
|
|
3766
|
+
onPoll?.({
|
|
3767
|
+
operation: "decrypt",
|
|
3768
|
+
requestId,
|
|
3769
|
+
attemptIndex,
|
|
3770
|
+
elapsedMs,
|
|
3771
|
+
intervalMs,
|
|
3772
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3773
|
+
});
|
|
3774
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3490
3775
|
throw new CofheError({
|
|
3491
3776
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3492
|
-
message: `decrypt polling timed out after ${
|
|
3777
|
+
message: `decrypt polling timed out after ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3493
3778
|
hint: "The request may still be processing. Try again later.",
|
|
3494
3779
|
context: {
|
|
3495
3780
|
thresholdNetworkUrl,
|
|
3496
3781
|
requestId,
|
|
3497
|
-
timeoutMs:
|
|
3782
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3498
3783
|
}
|
|
3499
3784
|
});
|
|
3500
3785
|
}
|
|
@@ -3566,45 +3851,14 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3566
3851
|
}
|
|
3567
3852
|
const statusResponse = assertDecryptStatusResponseV2(rawJson);
|
|
3568
3853
|
if (statusResponse.status === "COMPLETED") {
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
context: {
|
|
3575
|
-
thresholdNetworkUrl,
|
|
3576
|
-
requestId,
|
|
3577
|
-
statusResponse
|
|
3578
|
-
}
|
|
3579
|
-
});
|
|
3580
|
-
}
|
|
3581
|
-
if (statusResponse.error_message) {
|
|
3582
|
-
throw new CofheError({
|
|
3583
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3584
|
-
message: `decrypt request failed: ${statusResponse.error_message}`,
|
|
3585
|
-
context: {
|
|
3586
|
-
thresholdNetworkUrl,
|
|
3587
|
-
requestId,
|
|
3588
|
-
statusResponse
|
|
3589
|
-
}
|
|
3590
|
-
});
|
|
3591
|
-
}
|
|
3592
|
-
if (!Array.isArray(statusResponse.decrypted)) {
|
|
3593
|
-
throw new CofheError({
|
|
3594
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3595
|
-
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3596
|
-
context: {
|
|
3597
|
-
thresholdNetworkUrl,
|
|
3598
|
-
requestId,
|
|
3599
|
-
statusResponse
|
|
3600
|
-
}
|
|
3601
|
-
});
|
|
3602
|
-
}
|
|
3603
|
-
const decryptedValue = parseDecryptedBytesToBigInt(statusResponse.decrypted);
|
|
3604
|
-
const signature = normalizeTnSignature(statusResponse.signature);
|
|
3605
|
-
return { decryptedValue, signature };
|
|
3854
|
+
return parseCompletedDecryptResponseV2({
|
|
3855
|
+
value: statusResponse,
|
|
3856
|
+
thresholdNetworkUrl,
|
|
3857
|
+
requestId
|
|
3858
|
+
});
|
|
3606
3859
|
}
|
|
3607
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3860
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3861
|
+
attemptIndex += 1;
|
|
3608
3862
|
}
|
|
3609
3863
|
throw new CofheError({
|
|
3610
3864
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
@@ -3615,9 +3869,21 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3615
3869
|
}
|
|
3616
3870
|
});
|
|
3617
3871
|
}
|
|
3618
|
-
async function tnDecryptV2(
|
|
3619
|
-
const
|
|
3620
|
-
|
|
3872
|
+
async function tnDecryptV2(params) {
|
|
3873
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
3874
|
+
const overallStartTime = Date.now();
|
|
3875
|
+
const submitResult = await submitDecryptRequestV2(
|
|
3876
|
+
thresholdNetworkUrl,
|
|
3877
|
+
ctHash,
|
|
3878
|
+
chainId,
|
|
3879
|
+
permission,
|
|
3880
|
+
overallStartTime,
|
|
3881
|
+
onPoll
|
|
3882
|
+
);
|
|
3883
|
+
if (submitResult.kind === "completed") {
|
|
3884
|
+
return submitResult;
|
|
3885
|
+
}
|
|
3886
|
+
return await pollDecryptStatusV2(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
3621
3887
|
}
|
|
3622
3888
|
|
|
3623
3889
|
// core/decrypt/decryptForTxBuilder.ts
|
|
@@ -3626,6 +3892,7 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3626
3892
|
permitHash;
|
|
3627
3893
|
permit;
|
|
3628
3894
|
permitSelection = "unset";
|
|
3895
|
+
pollCallback;
|
|
3629
3896
|
constructor(params) {
|
|
3630
3897
|
super({
|
|
3631
3898
|
config: params.config,
|
|
@@ -3651,6 +3918,10 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3651
3918
|
getAccount() {
|
|
3652
3919
|
return this.account;
|
|
3653
3920
|
}
|
|
3921
|
+
onPoll(callback) {
|
|
3922
|
+
this.pollCallback = callback;
|
|
3923
|
+
return this;
|
|
3924
|
+
}
|
|
3654
3925
|
withPermit(permitOrPermitHash) {
|
|
3655
3926
|
if (this.permitSelection === "with-permit") {
|
|
3656
3927
|
throw new CofheError({
|
|
@@ -3778,7 +4049,13 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3778
4049
|
this.assertPublicClient();
|
|
3779
4050
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3780
4051
|
const permission = permit ? PermitUtils.getPermission(permit, true) : null;
|
|
3781
|
-
const { decryptedValue, signature } = await tnDecryptV2(
|
|
4052
|
+
const { decryptedValue, signature } = await tnDecryptV2({
|
|
4053
|
+
ctHash: this.ctHash,
|
|
4054
|
+
chainId: this.chainId,
|
|
4055
|
+
permission,
|
|
4056
|
+
thresholdNetworkUrl,
|
|
4057
|
+
onPoll: this.pollCallback
|
|
4058
|
+
});
|
|
3782
4059
|
return {
|
|
3783
4060
|
ctHash: this.ctHash,
|
|
3784
4061
|
decryptedValue,
|
|
@@ -3796,7 +4073,6 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3796
4073
|
const permit = await this.getResolvedPermit();
|
|
3797
4074
|
if (permit !== null) {
|
|
3798
4075
|
PermitUtils.validate(permit);
|
|
3799
|
-
PermitUtils.isValid(permit);
|
|
3800
4076
|
const chainId = permit._signedDomain.chainId;
|
|
3801
4077
|
if (chainId === hardhat2.id) {
|
|
3802
4078
|
return await this.mocksDecryptForTx(permit);
|
|
@@ -3817,6 +4093,35 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3817
4093
|
}
|
|
3818
4094
|
}
|
|
3819
4095
|
};
|
|
4096
|
+
var decryptResultSignerAbi = viem.parseAbi(["function decryptResultSigner() view returns (address)"]);
|
|
4097
|
+
var UINT_TYPE_MASK2 = 0x7fn;
|
|
4098
|
+
var TYPE_BYTE_OFFSET2 = 8n;
|
|
4099
|
+
var getEncryptionTypeFromCtHash2 = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET2 & UINT_TYPE_MASK2);
|
|
4100
|
+
var buildDecryptResultHash = (ctHash, cleartext, chainId) => {
|
|
4101
|
+
const encryptionType = getEncryptionTypeFromCtHash2(ctHash);
|
|
4102
|
+
return viem.keccak256(
|
|
4103
|
+
viem.encodePacked(["uint256", "uint32", "uint64", "uint256"], [cleartext, encryptionType, BigInt(chainId), ctHash])
|
|
4104
|
+
);
|
|
4105
|
+
};
|
|
4106
|
+
async function verifyDecryptResult(handle, cleartext, signature, publicClient) {
|
|
4107
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
4108
|
+
const expectedSigner = await publicClient.readContract({
|
|
4109
|
+
address: TASK_MANAGER_ADDRESS,
|
|
4110
|
+
abi: decryptResultSignerAbi,
|
|
4111
|
+
functionName: "decryptResultSigner",
|
|
4112
|
+
args: []
|
|
4113
|
+
});
|
|
4114
|
+
if (viem.isAddressEqual(expectedSigner, viem.zeroAddress))
|
|
4115
|
+
return true;
|
|
4116
|
+
const ctHash = BigInt(handle);
|
|
4117
|
+
const messageHash = buildDecryptResultHash(ctHash, cleartext, chainId);
|
|
4118
|
+
try {
|
|
4119
|
+
const recovered = await viem.recoverAddress({ hash: messageHash, signature });
|
|
4120
|
+
return viem.isAddressEqual(recovered, expectedSigner);
|
|
4121
|
+
} catch {
|
|
4122
|
+
return false;
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
3820
4125
|
|
|
3821
4126
|
// core/client.ts
|
|
3822
4127
|
var InitialConnectStore = {
|
|
@@ -3935,6 +4240,11 @@ function createCofheClientBase(opts) {
|
|
|
3935
4240
|
requireConnected: _requireConnected
|
|
3936
4241
|
});
|
|
3937
4242
|
}
|
|
4243
|
+
function verifyDecryptResult2(handle, cleartext, signature) {
|
|
4244
|
+
_requireConnected();
|
|
4245
|
+
const { publicClient } = connectStore.getState();
|
|
4246
|
+
return verifyDecryptResult(handle, cleartext, signature, publicClient);
|
|
4247
|
+
}
|
|
3938
4248
|
const _getChainIdAndAccount = (chainId, account) => {
|
|
3939
4249
|
const state = connectStore.getState();
|
|
3940
4250
|
const _chainId = chainId ?? state.chainId;
|
|
@@ -4017,6 +4327,7 @@ function createCofheClientBase(opts) {
|
|
|
4017
4327
|
},
|
|
4018
4328
|
// Utils (no context needed)
|
|
4019
4329
|
getHash: permits.getHash,
|
|
4330
|
+
export: permits.export,
|
|
4020
4331
|
serialize: permits.serialize,
|
|
4021
4332
|
deserialize: permits.deserialize
|
|
4022
4333
|
};
|
|
@@ -4045,6 +4356,7 @@ function createCofheClientBase(opts) {
|
|
|
4045
4356
|
*/
|
|
4046
4357
|
decryptHandle: decryptForView,
|
|
4047
4358
|
decryptForTx,
|
|
4359
|
+
verifyDecryptResult: verifyDecryptResult2,
|
|
4048
4360
|
permits: clientPermits
|
|
4049
4361
|
// Add SDK-specific methods below that require connection
|
|
4050
4362
|
// Example:
|
|
@@ -4054,12 +4366,19 @@ function createCofheClientBase(opts) {
|
|
|
4054
4366
|
// },
|
|
4055
4367
|
};
|
|
4056
4368
|
}
|
|
4057
|
-
|
|
4369
|
+
|
|
4370
|
+
// web/const.ts
|
|
4371
|
+
var hasDOM = typeof globalThis?.document !== "undefined" && typeof globalThis?.window !== "undefined";
|
|
4372
|
+
|
|
4373
|
+
// web/storage.ts
|
|
4374
|
+
var createWebStorage = (opts = { enableLog: false }) => {
|
|
4375
|
+
if (!hasDOM)
|
|
4376
|
+
throw new Error("createWebStorage can only be used in a browser environment");
|
|
4058
4377
|
const client = iframeSharedStorage.constructClient({
|
|
4059
4378
|
iframe: {
|
|
4060
4379
|
src: "https://iframe-shared-storage.vercel.app/hub.html",
|
|
4061
4380
|
messagingOptions: {
|
|
4062
|
-
enableLog: "both"
|
|
4381
|
+
enableLog: opts.enableLog ? "both" : void 0
|
|
4063
4382
|
},
|
|
4064
4383
|
iframeReadyTimeoutMs: 3e4,
|
|
4065
4384
|
// if the iframe is not initied during this interval AND a reuqest is made, such request will throw an error
|
|
@@ -4082,6 +4401,16 @@ var createWebStorage = () => {
|
|
|
4082
4401
|
}
|
|
4083
4402
|
};
|
|
4084
4403
|
};
|
|
4404
|
+
function createSsrStorage() {
|
|
4405
|
+
console.warn("using no-op server-side SSR storage");
|
|
4406
|
+
return {
|
|
4407
|
+
getItem: async () => null,
|
|
4408
|
+
setItem: async () => {
|
|
4409
|
+
},
|
|
4410
|
+
removeItem: async () => {
|
|
4411
|
+
}
|
|
4412
|
+
};
|
|
4413
|
+
}
|
|
4085
4414
|
|
|
4086
4415
|
// web/workerManager.ts
|
|
4087
4416
|
var ZkProveWorkerManager = class {
|
|
@@ -4107,7 +4436,7 @@ var ZkProveWorkerManager = class {
|
|
|
4107
4436
|
return;
|
|
4108
4437
|
}
|
|
4109
4438
|
try {
|
|
4110
|
-
this.worker = new Worker(new URL("./zkProve.worker.js", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('out.js', document.baseURI).href))), { type: "module" });
|
|
4439
|
+
this.worker = new Worker(new URL("./zkProve.worker.js", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('out.js', document.baseURI).href))), { type: "module" });
|
|
4111
4440
|
} catch (error) {
|
|
4112
4441
|
reject(new Error(`Failed to create worker: ${error}`));
|
|
4113
4442
|
return;
|
|
@@ -4237,16 +4566,22 @@ var fromHexString2 = (hexString) => {
|
|
|
4237
4566
|
return new Uint8Array();
|
|
4238
4567
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
4239
4568
|
};
|
|
4569
|
+
var _deserializeTfhePublicKey = (buff) => {
|
|
4570
|
+
return init.TfheCompactPublicKey.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
4571
|
+
};
|
|
4572
|
+
var _deserializeCompactPkeCrs = (buff) => {
|
|
4573
|
+
return init.CompactPkeCrs.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
4574
|
+
};
|
|
4240
4575
|
var tfhePublicKeyDeserializer = (buff) => {
|
|
4241
|
-
|
|
4576
|
+
_deserializeTfhePublicKey(buff);
|
|
4242
4577
|
};
|
|
4243
4578
|
var compactPkeCrsDeserializer = (buff) => {
|
|
4244
|
-
|
|
4579
|
+
_deserializeCompactPkeCrs(buff);
|
|
4245
4580
|
};
|
|
4246
4581
|
var zkBuilderAndCrsGenerator = (fhe, crs) => {
|
|
4247
|
-
const fhePublicKey =
|
|
4582
|
+
const fhePublicKey = _deserializeTfhePublicKey(fhe);
|
|
4248
4583
|
const zkBuilder = init.ProvenCompactCiphertextList.builder(fhePublicKey);
|
|
4249
|
-
const zkCrs =
|
|
4584
|
+
const zkCrs = _deserializeCompactPkeCrs(crs);
|
|
4250
4585
|
return { zkBuilder, zkCrs };
|
|
4251
4586
|
};
|
|
4252
4587
|
async function zkProveWithWorker2(fheKeyHex, crsHex, items, metadata) {
|
|
@@ -4261,7 +4596,7 @@ function createCofheConfig(config) {
|
|
|
4261
4596
|
return createCofheConfigBase({
|
|
4262
4597
|
environment: "web",
|
|
4263
4598
|
...config,
|
|
4264
|
-
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createWebStorage()
|
|
4599
|
+
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? (hasDOM ? createWebStorage() : createSsrStorage())
|
|
4265
4600
|
});
|
|
4266
4601
|
}
|
|
4267
4602
|
function createCofheClient(config) {
|
|
@@ -4291,4 +4626,6 @@ exports.areWorkersAvailable = areWorkersAvailable;
|
|
|
4291
4626
|
exports.createCofheClient = createCofheClient;
|
|
4292
4627
|
exports.createCofheClientWithCustomWorker = createCofheClientWithCustomWorker;
|
|
4293
4628
|
exports.createCofheConfig = createCofheConfig;
|
|
4629
|
+
exports.createSsrStorage = createSsrStorage;
|
|
4630
|
+
exports.hasDOM = hasDOM;
|
|
4294
4631
|
exports.terminateWorker = terminateWorker;
|