@cofhe/sdk 0.4.0 → 0.5.1
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 +38 -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 +604 -256
- package/dist/web.d.cts +8 -4
- package/dist/web.d.ts +8 -4
- package/dist/web.js +49 -14
- package/dist/zkProve.worker.cjs +72 -64
- package/dist/zkProve.worker.js +71 -64
- 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 +40 -11
- 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 +94 -84
- 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/core.cjs
CHANGED
|
@@ -9,25 +9,9 @@ var middleware = require('zustand/middleware');
|
|
|
9
9
|
var immer = require('immer');
|
|
10
10
|
var nacl = require('tweetnacl');
|
|
11
11
|
|
|
12
|
-
function
|
|
13
|
-
if (e && e.__esModule) return e;
|
|
14
|
-
var n = Object.create(null);
|
|
15
|
-
if (e) {
|
|
16
|
-
Object.keys(e).forEach(function (k) {
|
|
17
|
-
if (k !== 'default') {
|
|
18
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () { return e[k]; }
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
n.default = e;
|
|
27
|
-
return Object.freeze(n);
|
|
28
|
-
}
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
29
13
|
|
|
30
|
-
var
|
|
14
|
+
var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
31
15
|
|
|
32
16
|
// core/client.ts
|
|
33
17
|
|
|
@@ -166,6 +150,18 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
166
150
|
};
|
|
167
151
|
var isCofheError = (error) => error instanceof CofheError;
|
|
168
152
|
|
|
153
|
+
// core/consts.ts
|
|
154
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
155
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
156
|
+
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
157
|
+
var TEST_BED_ADDRESS = "0x0000000000000000000000000000000000005003";
|
|
158
|
+
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
159
|
+
var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
|
|
160
|
+
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
161
|
+
var TFHE_RS_ZK_MAX_BITS = 2048;
|
|
162
|
+
var TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = BigInt(1 << 30);
|
|
163
|
+
var TFHE_RS_KEY_VERSION = 2;
|
|
164
|
+
|
|
169
165
|
// core/types.ts
|
|
170
166
|
var FheTypes = /* @__PURE__ */ ((FheTypes2) => {
|
|
171
167
|
FheTypes2[FheTypes2["Bool"] = 0] = "Bool";
|
|
@@ -395,7 +391,6 @@ var MAX_UINT32 = 4294967295n;
|
|
|
395
391
|
var MAX_UINT64 = 18446744073709551615n;
|
|
396
392
|
var MAX_UINT128 = 340282366920938463463374607431768211455n;
|
|
397
393
|
var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
|
|
398
|
-
var MAX_ENCRYPTABLE_BITS = 2048;
|
|
399
394
|
var zkPack = (items, builder) => {
|
|
400
395
|
let totalBits = 0;
|
|
401
396
|
for (const item of items) {
|
|
@@ -459,14 +454,14 @@ var zkPack = (items, builder) => {
|
|
|
459
454
|
}
|
|
460
455
|
}
|
|
461
456
|
}
|
|
462
|
-
if (totalBits >
|
|
457
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
463
458
|
throw new CofheError({
|
|
464
459
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
465
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
466
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
460
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
461
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
467
462
|
context: {
|
|
468
463
|
totalBits,
|
|
469
|
-
maxBits:
|
|
464
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
470
465
|
items
|
|
471
466
|
}
|
|
472
467
|
});
|
|
@@ -485,7 +480,7 @@ var zkProve = async (builder, crs, metadata) => {
|
|
|
485
480
|
1
|
|
486
481
|
// ZkComputeLoad.Verify
|
|
487
482
|
);
|
|
488
|
-
resolve(compactList.
|
|
483
|
+
resolve(compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT));
|
|
489
484
|
}, 0);
|
|
490
485
|
});
|
|
491
486
|
};
|
|
@@ -661,17 +656,6 @@ var MockZkVerifierAbi = [
|
|
|
661
656
|
},
|
|
662
657
|
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
663
658
|
];
|
|
664
|
-
|
|
665
|
-
// core/consts.ts
|
|
666
|
-
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
667
|
-
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
668
|
-
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
669
|
-
var TEST_BED_ADDRESS = "0x0000000000000000000000000000000000005003";
|
|
670
|
-
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
671
|
-
var MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = "0x6E12D8C87503D4287c294f2Fdef96ACd9DFf6bd2";
|
|
672
|
-
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
673
|
-
|
|
674
|
-
// core/encrypt/cofheMocksZkVerifySign.ts
|
|
675
659
|
function createMockZkVerifierSigner() {
|
|
676
660
|
return viem.createWalletClient({
|
|
677
661
|
chain: chains.hardhat,
|
|
@@ -713,14 +697,14 @@ async function cofheMocksCheckEncryptableBits(items) {
|
|
|
713
697
|
}
|
|
714
698
|
}
|
|
715
699
|
}
|
|
716
|
-
if (totalBits >
|
|
700
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
717
701
|
throw new CofheError({
|
|
718
702
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
719
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
720
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
703
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
704
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
721
705
|
context: {
|
|
722
706
|
totalBits,
|
|
723
|
-
maxBits:
|
|
707
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
724
708
|
items
|
|
725
709
|
}
|
|
726
710
|
});
|
|
@@ -994,6 +978,7 @@ function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
|
994
978
|
}
|
|
995
979
|
return url;
|
|
996
980
|
}
|
|
981
|
+
var KEYSTORE_NAME = `cofhesdk-keys-v${TFHE_RS_KEY_VERSION}`;
|
|
997
982
|
function isValidPersistedState(state) {
|
|
998
983
|
if (state && typeof state === "object") {
|
|
999
984
|
if ("fhe" in state && "crs" in state) {
|
|
@@ -1048,7 +1033,7 @@ function createKeysStore(storage) {
|
|
|
1048
1033
|
};
|
|
1049
1034
|
const clearKeysStorage = async () => {
|
|
1050
1035
|
if (storage) {
|
|
1051
|
-
await storage.removeItem(
|
|
1036
|
+
await storage.removeItem(KEYSTORE_NAME);
|
|
1052
1037
|
}
|
|
1053
1038
|
};
|
|
1054
1039
|
const rehydrateKeysStore = async () => {
|
|
@@ -1078,7 +1063,7 @@ function createStoreWithPersit(storage) {
|
|
|
1078
1063
|
if (_error)
|
|
1079
1064
|
throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
|
|
1080
1065
|
},
|
|
1081
|
-
name:
|
|
1066
|
+
name: KEYSTORE_NAME,
|
|
1082
1067
|
storage: middleware.createJSONStorage(() => storage),
|
|
1083
1068
|
merge: (persistedState, currentState) => {
|
|
1084
1069
|
const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
|
|
@@ -1803,7 +1788,7 @@ var SealingKey = class _SealingKey {
|
|
|
1803
1788
|
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
1804
1789
|
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
1805
1790
|
const privateKeyBytes = fromHexString(this.privateKey);
|
|
1806
|
-
const decryptedMessage =
|
|
1791
|
+
const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
|
|
1807
1792
|
if (!decryptedMessage) {
|
|
1808
1793
|
throw new Error("Failed to decrypt message");
|
|
1809
1794
|
}
|
|
@@ -1836,9 +1821,9 @@ var SealingKey = class _SealingKey {
|
|
|
1836
1821
|
static seal = (value, publicKey) => {
|
|
1837
1822
|
isString(publicKey);
|
|
1838
1823
|
isBigIntOrNumber(value);
|
|
1839
|
-
const ephemeralKeyPair =
|
|
1840
|
-
const nonce =
|
|
1841
|
-
const encryptedMessage =
|
|
1824
|
+
const ephemeralKeyPair = nacl__default.default.box.keyPair();
|
|
1825
|
+
const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
|
|
1826
|
+
const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
1842
1827
|
return {
|
|
1843
1828
|
data: encryptedMessage,
|
|
1844
1829
|
public_key: ephemeralKeyPair.publicKey,
|
|
@@ -1847,7 +1832,7 @@ var SealingKey = class _SealingKey {
|
|
|
1847
1832
|
};
|
|
1848
1833
|
};
|
|
1849
1834
|
var GenerateSealingKey = () => {
|
|
1850
|
-
const sodiumKeypair =
|
|
1835
|
+
const sodiumKeypair = nacl__default.default.box.keyPair();
|
|
1851
1836
|
return new SealingKey(toHexString2(sodiumKeypair.secretKey), toHexString2(sodiumKeypair.publicKey));
|
|
1852
1837
|
};
|
|
1853
1838
|
var SerializedSealingPair = zod.z.object({
|
|
@@ -2005,9 +1990,9 @@ var ValidationUtils = {
|
|
|
2005
1990
|
return false;
|
|
2006
1991
|
},
|
|
2007
1992
|
/**
|
|
2008
|
-
*
|
|
1993
|
+
* Checks that a permit is signed and not expired.
|
|
2009
1994
|
*/
|
|
2010
|
-
|
|
1995
|
+
isSignedAndNotExpired: (permit) => {
|
|
2011
1996
|
if (ValidationUtils.isExpired(permit)) {
|
|
2012
1997
|
return { valid: false, error: "expired" };
|
|
2013
1998
|
}
|
|
@@ -2015,6 +2000,34 @@ var ValidationUtils = {
|
|
|
2015
2000
|
return { valid: false, error: "not-signed" };
|
|
2016
2001
|
}
|
|
2017
2002
|
return { valid: true, error: null };
|
|
2003
|
+
},
|
|
2004
|
+
/**
|
|
2005
|
+
* Asserts that a permit is signed and not expired.
|
|
2006
|
+
*
|
|
2007
|
+
* Throws `Error` with message:
|
|
2008
|
+
* - `Permit is expired`
|
|
2009
|
+
* - `Permit is not signed`
|
|
2010
|
+
*/
|
|
2011
|
+
assertSignedAndNotExpired: (permit) => {
|
|
2012
|
+
const result = ValidationUtils.isSignedAndNotExpired(permit);
|
|
2013
|
+
if (result.valid)
|
|
2014
|
+
return;
|
|
2015
|
+
if (result.error === "expired") {
|
|
2016
|
+
throw new Error("Permit is expired");
|
|
2017
|
+
}
|
|
2018
|
+
if (result.error === "not-signed") {
|
|
2019
|
+
throw new Error("Permit is not signed");
|
|
2020
|
+
}
|
|
2021
|
+
throw new Error("Permit is invalid");
|
|
2022
|
+
},
|
|
2023
|
+
isValid: (permit) => {
|
|
2024
|
+
const schema = permit.type === "self" ? SelfPermitValidator : permit.type === "sharing" ? SharingPermitValidator : permit.type === "recipient" ? ImportPermitValidator : null;
|
|
2025
|
+
if (schema == null)
|
|
2026
|
+
return { valid: false, error: "invalid-schema" };
|
|
2027
|
+
const schemaResult = schema.safeParse(permit);
|
|
2028
|
+
if (!schemaResult.success)
|
|
2029
|
+
return { valid: false, error: "invalid-schema" };
|
|
2030
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
2018
2031
|
}
|
|
2019
2032
|
};
|
|
2020
2033
|
|
|
@@ -2396,9 +2409,9 @@ var PermitUtils = {
|
|
|
2396
2409
|
};
|
|
2397
2410
|
},
|
|
2398
2411
|
/**
|
|
2399
|
-
* Validate a permit
|
|
2412
|
+
* Validate a permit (schema-level validation)
|
|
2400
2413
|
*/
|
|
2401
|
-
|
|
2414
|
+
validateSchema: (permit) => {
|
|
2402
2415
|
if (permit.type === "self") {
|
|
2403
2416
|
return validateSelfPermit(permit);
|
|
2404
2417
|
} else if (permit.type === "sharing") {
|
|
@@ -2409,12 +2422,27 @@ var PermitUtils = {
|
|
|
2409
2422
|
throw new Error("Invalid permit type");
|
|
2410
2423
|
}
|
|
2411
2424
|
},
|
|
2425
|
+
/**
|
|
2426
|
+
* Validate a permit (holistic validation).
|
|
2427
|
+
*
|
|
2428
|
+
* This validates:
|
|
2429
|
+
* - Permit schema (shape + invariants)
|
|
2430
|
+
* - Permit is signed
|
|
2431
|
+
* - Permit is not expired
|
|
2432
|
+
*
|
|
2433
|
+
* For schema-only validation, use `validateSchema(permit)`.
|
|
2434
|
+
*/
|
|
2435
|
+
validate: (permit) => {
|
|
2436
|
+
const validated = PermitUtils.validateSchema(permit);
|
|
2437
|
+
ValidationUtils.assertSignedAndNotExpired(validated);
|
|
2438
|
+
return validated;
|
|
2439
|
+
},
|
|
2412
2440
|
/**
|
|
2413
2441
|
* Get the permission object from a permit (for use in contracts)
|
|
2414
2442
|
*/
|
|
2415
2443
|
getPermission: (permit, skipValidation = false) => {
|
|
2416
2444
|
if (!skipValidation) {
|
|
2417
|
-
PermitUtils.
|
|
2445
|
+
PermitUtils.validateSchema(permit);
|
|
2418
2446
|
}
|
|
2419
2447
|
return {
|
|
2420
2448
|
issuer: permit.issuer,
|
|
@@ -2480,8 +2508,17 @@ var PermitUtils = {
|
|
|
2480
2508
|
return ValidationUtils.isSigned(permit);
|
|
2481
2509
|
},
|
|
2482
2510
|
/**
|
|
2483
|
-
* Check if permit is
|
|
2511
|
+
* Check if permit is signed and not expired
|
|
2512
|
+
*/
|
|
2513
|
+
isSignedAndNotExpired: (permit) => {
|
|
2514
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
2515
|
+
},
|
|
2516
|
+
/**
|
|
2517
|
+
* Assert that permit is signed and not expired
|
|
2484
2518
|
*/
|
|
2519
|
+
assertSignedAndNotExpired: (permit) => {
|
|
2520
|
+
return ValidationUtils.assertSignedAndNotExpired(permit);
|
|
2521
|
+
},
|
|
2485
2522
|
isValid: (permit) => {
|
|
2486
2523
|
return ValidationUtils.isValid(permit);
|
|
2487
2524
|
},
|
|
@@ -2659,6 +2696,9 @@ var importShared = async (options, publicClient, walletClient) => {
|
|
|
2659
2696
|
var getHash = (permit) => {
|
|
2660
2697
|
return PermitUtils.getHash(permit);
|
|
2661
2698
|
};
|
|
2699
|
+
var exportShared = (permit) => {
|
|
2700
|
+
return PermitUtils.export(permit);
|
|
2701
|
+
};
|
|
2662
2702
|
var serialize = (permit) => {
|
|
2663
2703
|
return PermitUtils.serialize(permit);
|
|
2664
2704
|
};
|
|
@@ -2709,6 +2749,7 @@ var permits = {
|
|
|
2709
2749
|
getOrCreateSelfPermit,
|
|
2710
2750
|
getOrCreateSharingPermit,
|
|
2711
2751
|
getHash,
|
|
2752
|
+
export: exportShared,
|
|
2712
2753
|
serialize,
|
|
2713
2754
|
deserialize,
|
|
2714
2755
|
getPermit: getPermit2,
|
|
@@ -2951,9 +2992,19 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
|
|
|
2951
2992
|
return unsealed;
|
|
2952
2993
|
}
|
|
2953
2994
|
|
|
2995
|
+
// core/decrypt/polling.ts
|
|
2996
|
+
function computeMinuteRampPollIntervalMs(elapsedMs, params) {
|
|
2997
|
+
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
|
2998
|
+
const intervalSeconds = 1 + Math.floor(elapsedSeconds / 60);
|
|
2999
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
3000
|
+
return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
|
|
3001
|
+
}
|
|
3002
|
+
|
|
2954
3003
|
// core/decrypt/tnSealOutputV2.ts
|
|
2955
3004
|
var POLL_INTERVAL_MS = 1e3;
|
|
2956
|
-
var
|
|
3005
|
+
var POLL_MAX_INTERVAL_MS = 1e4;
|
|
3006
|
+
var SEAL_OUTPUT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3007
|
+
var SUBMIT_RETRY_INTERVAL_MS = 1e3;
|
|
2957
3008
|
function numberArrayToUint8Array(arr) {
|
|
2958
3009
|
return new Uint8Array(arr);
|
|
2959
3010
|
}
|
|
@@ -2970,93 +3021,193 @@ function convertSealedData(sealed) {
|
|
|
2970
3021
|
nonce: numberArrayToUint8Array(sealed.nonce)
|
|
2971
3022
|
};
|
|
2972
3023
|
}
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
method: "POST",
|
|
2983
|
-
headers: {
|
|
2984
|
-
"Content-Type": "application/json"
|
|
2985
|
-
},
|
|
2986
|
-
body: JSON.stringify(body)
|
|
2987
|
-
});
|
|
2988
|
-
} catch (e) {
|
|
2989
|
-
throw new CofheError({
|
|
2990
|
-
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2991
|
-
message: `sealOutput request failed`,
|
|
2992
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2993
|
-
cause: e instanceof Error ? e : void 0,
|
|
2994
|
-
context: {
|
|
2995
|
-
thresholdNetworkUrl,
|
|
2996
|
-
body
|
|
2997
|
-
}
|
|
2998
|
-
});
|
|
3024
|
+
function getSealedDataFromSubmitResponse(value) {
|
|
3025
|
+
if (value.sealed)
|
|
3026
|
+
return value.sealed;
|
|
3027
|
+
if (Array.isArray(value.sealed_data) && Array.isArray(value.ephemeral_public_key) && Array.isArray(value.nonce)) {
|
|
3028
|
+
return {
|
|
3029
|
+
data: value.sealed_data,
|
|
3030
|
+
public_key: value.ephemeral_public_key,
|
|
3031
|
+
nonce: value.nonce
|
|
3032
|
+
};
|
|
2999
3033
|
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
errorMessage = response.statusText || errorMessage;
|
|
3007
|
-
}
|
|
3034
|
+
return void 0;
|
|
3035
|
+
}
|
|
3036
|
+
function parseCompletedSealOutputResponse(params) {
|
|
3037
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
3038
|
+
if (value.is_succeed === false) {
|
|
3039
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
3008
3040
|
throw new CofheError({
|
|
3009
3041
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3010
3042
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
3011
|
-
hint: "Check the threshold network URL and request parameters.",
|
|
3012
3043
|
context: {
|
|
3013
3044
|
thresholdNetworkUrl,
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
body
|
|
3045
|
+
requestId,
|
|
3046
|
+
response: value
|
|
3017
3047
|
}
|
|
3018
3048
|
});
|
|
3019
3049
|
}
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
submitResponse = await response.json();
|
|
3023
|
-
} catch (e) {
|
|
3050
|
+
const sealed = "sealed" in value ? value.sealed : getSealedDataFromSubmitResponse(value);
|
|
3051
|
+
if (!sealed) {
|
|
3024
3052
|
throw new CofheError({
|
|
3025
|
-
code: "
|
|
3026
|
-
message: `
|
|
3027
|
-
cause: e instanceof Error ? e : void 0,
|
|
3053
|
+
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
3054
|
+
message: `sealOutput request completed but returned no sealed data`,
|
|
3028
3055
|
context: {
|
|
3029
3056
|
thresholdNetworkUrl,
|
|
3030
|
-
|
|
3057
|
+
requestId,
|
|
3058
|
+
response: value
|
|
3031
3059
|
}
|
|
3032
3060
|
});
|
|
3033
3061
|
}
|
|
3034
|
-
|
|
3062
|
+
return convertSealedData(sealed);
|
|
3063
|
+
}
|
|
3064
|
+
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
3065
|
+
const body = {
|
|
3066
|
+
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3067
|
+
host_chain_id: chainId,
|
|
3068
|
+
permit: permission
|
|
3069
|
+
};
|
|
3070
|
+
let attemptIndex = 0;
|
|
3071
|
+
for (; ; ) {
|
|
3072
|
+
let response;
|
|
3073
|
+
try {
|
|
3074
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
|
|
3075
|
+
method: "POST",
|
|
3076
|
+
headers: {
|
|
3077
|
+
"Content-Type": "application/json"
|
|
3078
|
+
},
|
|
3079
|
+
body: JSON.stringify(body)
|
|
3080
|
+
});
|
|
3081
|
+
} catch (e) {
|
|
3082
|
+
throw new CofheError({
|
|
3083
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3084
|
+
message: `sealOutput request failed`,
|
|
3085
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3086
|
+
cause: e instanceof Error ? e : void 0,
|
|
3087
|
+
context: {
|
|
3088
|
+
thresholdNetworkUrl,
|
|
3089
|
+
body,
|
|
3090
|
+
attemptIndex
|
|
3091
|
+
}
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
if (!response.ok) {
|
|
3095
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
3096
|
+
try {
|
|
3097
|
+
const errorBody = await response.json();
|
|
3098
|
+
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
3099
|
+
} catch {
|
|
3100
|
+
errorMessage = response.statusText || errorMessage;
|
|
3101
|
+
}
|
|
3102
|
+
throw new CofheError({
|
|
3103
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3104
|
+
message: `sealOutput request failed: ${errorMessage}`,
|
|
3105
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3106
|
+
context: {
|
|
3107
|
+
thresholdNetworkUrl,
|
|
3108
|
+
status: response.status,
|
|
3109
|
+
statusText: response.statusText,
|
|
3110
|
+
body,
|
|
3111
|
+
attemptIndex
|
|
3112
|
+
}
|
|
3113
|
+
});
|
|
3114
|
+
}
|
|
3115
|
+
let submitResponse;
|
|
3116
|
+
if (response.status !== 204) {
|
|
3117
|
+
try {
|
|
3118
|
+
submitResponse = await response.json();
|
|
3119
|
+
} catch (e) {
|
|
3120
|
+
throw new CofheError({
|
|
3121
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3122
|
+
message: `Failed to parse sealOutput submit response`,
|
|
3123
|
+
cause: e instanceof Error ? e : void 0,
|
|
3124
|
+
context: {
|
|
3125
|
+
thresholdNetworkUrl,
|
|
3126
|
+
body,
|
|
3127
|
+
attemptIndex
|
|
3128
|
+
}
|
|
3129
|
+
});
|
|
3130
|
+
}
|
|
3131
|
+
if (getSealedDataFromSubmitResponse(submitResponse)) {
|
|
3132
|
+
return {
|
|
3133
|
+
kind: "completed",
|
|
3134
|
+
sealed: parseCompletedSealOutputResponse({
|
|
3135
|
+
value: submitResponse,
|
|
3136
|
+
thresholdNetworkUrl,
|
|
3137
|
+
requestId: submitResponse.request_id
|
|
3138
|
+
})
|
|
3139
|
+
};
|
|
3140
|
+
}
|
|
3141
|
+
if (submitResponse.request_id) {
|
|
3142
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
if (response.status === 204) {
|
|
3146
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3147
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
3148
|
+
throw new CofheError({
|
|
3149
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3150
|
+
message: `sealOutput submit retried without receiving request_id for ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
3151
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
3152
|
+
context: {
|
|
3153
|
+
thresholdNetworkUrl,
|
|
3154
|
+
body,
|
|
3155
|
+
attemptIndex,
|
|
3156
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
|
|
3157
|
+
submitResponse,
|
|
3158
|
+
status: response.status
|
|
3159
|
+
}
|
|
3160
|
+
});
|
|
3161
|
+
}
|
|
3162
|
+
onPoll?.({
|
|
3163
|
+
operation: "sealoutput",
|
|
3164
|
+
requestId: "",
|
|
3165
|
+
attemptIndex,
|
|
3166
|
+
elapsedMs,
|
|
3167
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS,
|
|
3168
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3169
|
+
});
|
|
3170
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS));
|
|
3171
|
+
attemptIndex += 1;
|
|
3172
|
+
continue;
|
|
3173
|
+
}
|
|
3035
3174
|
throw new CofheError({
|
|
3036
3175
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3037
3176
|
message: `sealOutput submit response missing request_id`,
|
|
3038
3177
|
context: {
|
|
3039
3178
|
thresholdNetworkUrl,
|
|
3040
3179
|
body,
|
|
3041
|
-
submitResponse
|
|
3180
|
+
submitResponse,
|
|
3181
|
+
attemptIndex
|
|
3042
3182
|
}
|
|
3043
3183
|
});
|
|
3044
3184
|
}
|
|
3045
|
-
return submitResponse.request_id;
|
|
3046
3185
|
}
|
|
3047
|
-
async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3186
|
+
async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
3187
|
+
let attemptIndex = 0;
|
|
3188
|
+
while (true) {
|
|
3189
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3190
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3191
|
+
minIntervalMs: POLL_INTERVAL_MS,
|
|
3192
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS
|
|
3193
|
+
});
|
|
3194
|
+
onPoll?.({
|
|
3195
|
+
operation: "sealoutput",
|
|
3196
|
+
requestId,
|
|
3197
|
+
attemptIndex,
|
|
3198
|
+
elapsedMs,
|
|
3199
|
+
intervalMs,
|
|
3200
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3201
|
+
});
|
|
3202
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
3052
3203
|
throw new CofheError({
|
|
3053
3204
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
3054
|
-
message: `sealOutput polling timed out after ${
|
|
3205
|
+
message: `sealOutput polling timed out after ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
3055
3206
|
hint: "The request may still be processing. Try again later.",
|
|
3056
3207
|
context: {
|
|
3057
3208
|
thresholdNetworkUrl,
|
|
3058
3209
|
requestId,
|
|
3059
|
-
timeoutMs:
|
|
3210
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3060
3211
|
}
|
|
3061
3212
|
});
|
|
3062
3213
|
}
|
|
@@ -3125,32 +3276,14 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
3125
3276
|
});
|
|
3126
3277
|
}
|
|
3127
3278
|
if (statusResponse.status === "COMPLETED") {
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
context: {
|
|
3134
|
-
thresholdNetworkUrl,
|
|
3135
|
-
requestId,
|
|
3136
|
-
statusResponse
|
|
3137
|
-
}
|
|
3138
|
-
});
|
|
3139
|
-
}
|
|
3140
|
-
if (!statusResponse.sealed) {
|
|
3141
|
-
throw new CofheError({
|
|
3142
|
-
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
3143
|
-
message: `sealOutput request completed but returned no sealed data`,
|
|
3144
|
-
context: {
|
|
3145
|
-
thresholdNetworkUrl,
|
|
3146
|
-
requestId,
|
|
3147
|
-
statusResponse
|
|
3148
|
-
}
|
|
3149
|
-
});
|
|
3150
|
-
}
|
|
3151
|
-
return convertSealedData(statusResponse.sealed);
|
|
3279
|
+
return parseCompletedSealOutputResponse({
|
|
3280
|
+
value: statusResponse,
|
|
3281
|
+
thresholdNetworkUrl,
|
|
3282
|
+
requestId
|
|
3283
|
+
});
|
|
3152
3284
|
}
|
|
3153
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3285
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3286
|
+
attemptIndex += 1;
|
|
3154
3287
|
}
|
|
3155
3288
|
throw new CofheError({
|
|
3156
3289
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
@@ -3161,9 +3294,21 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
3161
3294
|
}
|
|
3162
3295
|
});
|
|
3163
3296
|
}
|
|
3164
|
-
async function tnSealOutputV2(
|
|
3165
|
-
const
|
|
3166
|
-
|
|
3297
|
+
async function tnSealOutputV2(params) {
|
|
3298
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
3299
|
+
const overallStartTime = Date.now();
|
|
3300
|
+
const submitResult = await submitSealOutputRequest(
|
|
3301
|
+
thresholdNetworkUrl,
|
|
3302
|
+
ctHash,
|
|
3303
|
+
chainId,
|
|
3304
|
+
permission,
|
|
3305
|
+
overallStartTime,
|
|
3306
|
+
onPoll
|
|
3307
|
+
);
|
|
3308
|
+
if (submitResult.kind === "completed") {
|
|
3309
|
+
return submitResult.sealed;
|
|
3310
|
+
}
|
|
3311
|
+
return await pollSealOutputStatus(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
3167
3312
|
}
|
|
3168
3313
|
|
|
3169
3314
|
// core/decrypt/decryptForViewBuilder.ts
|
|
@@ -3172,6 +3317,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3172
3317
|
utype;
|
|
3173
3318
|
permitHash;
|
|
3174
3319
|
permit;
|
|
3320
|
+
pollCallback;
|
|
3175
3321
|
constructor(params) {
|
|
3176
3322
|
super({
|
|
3177
3323
|
config: params.config,
|
|
@@ -3228,6 +3374,10 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3228
3374
|
getAccount() {
|
|
3229
3375
|
return this.account;
|
|
3230
3376
|
}
|
|
3377
|
+
onPoll(callback) {
|
|
3378
|
+
this.pollCallback = callback;
|
|
3379
|
+
return this;
|
|
3380
|
+
}
|
|
3231
3381
|
withPermit(permitOrPermitHash) {
|
|
3232
3382
|
if (typeof permitOrPermitHash === "string") {
|
|
3233
3383
|
this.permitHash = permitOrPermitHash;
|
|
@@ -3351,7 +3501,13 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3351
3501
|
this.assertPublicClient();
|
|
3352
3502
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3353
3503
|
const permission = PermitUtils.getPermission(permit, true);
|
|
3354
|
-
const sealed = await tnSealOutputV2(
|
|
3504
|
+
const sealed = await tnSealOutputV2({
|
|
3505
|
+
ctHash: this.ctHash,
|
|
3506
|
+
chainId: this.chainId,
|
|
3507
|
+
permission,
|
|
3508
|
+
thresholdNetworkUrl,
|
|
3509
|
+
onPoll: this.pollCallback
|
|
3510
|
+
});
|
|
3355
3511
|
return PermitUtils.unseal(permit, sealed);
|
|
3356
3512
|
}
|
|
3357
3513
|
/**
|
|
@@ -3379,7 +3535,6 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3379
3535
|
this.validateUtypeOrThrow();
|
|
3380
3536
|
const permit = await this.getResolvedPermit();
|
|
3381
3537
|
PermitUtils.validate(permit);
|
|
3382
|
-
PermitUtils.isValid(permit);
|
|
3383
3538
|
const chainId = permit._signedDomain.chainId;
|
|
3384
3539
|
let unsealed;
|
|
3385
3540
|
if (chainId === hardhat2.id) {
|
|
@@ -3390,6 +3545,9 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3390
3545
|
return convertViaUtype(this.utype, unsealed);
|
|
3391
3546
|
}
|
|
3392
3547
|
};
|
|
3548
|
+
var UINT_TYPE_MASK = 0x7fn;
|
|
3549
|
+
var TYPE_BYTE_OFFSET = 8n;
|
|
3550
|
+
var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
|
|
3393
3551
|
async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
3394
3552
|
let allowed;
|
|
3395
3553
|
let error;
|
|
@@ -3427,7 +3585,13 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
|
3427
3585
|
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3428
3586
|
});
|
|
3429
3587
|
}
|
|
3430
|
-
const
|
|
3588
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
3589
|
+
const normalizedCtHash = BigInt(ctHash);
|
|
3590
|
+
const encryptionType = getEncryptionTypeFromCtHash(normalizedCtHash);
|
|
3591
|
+
const packed = viem.encodePacked(
|
|
3592
|
+
["uint256", "uint32", "uint64", "uint256"],
|
|
3593
|
+
[decryptedValue, encryptionType, BigInt(chainId), normalizedCtHash]
|
|
3594
|
+
);
|
|
3431
3595
|
const messageHash = viem.keccak256(packed);
|
|
3432
3596
|
const signature = await accounts.sign({
|
|
3433
3597
|
hash: messageHash,
|
|
@@ -3499,7 +3663,9 @@ function parseDecryptedBytesToBigInt(decrypted) {
|
|
|
3499
3663
|
|
|
3500
3664
|
// core/decrypt/tnDecryptV2.ts
|
|
3501
3665
|
var POLL_INTERVAL_MS2 = 1e3;
|
|
3502
|
-
var
|
|
3666
|
+
var POLL_MAX_INTERVAL_MS2 = 1e4;
|
|
3667
|
+
var DECRYPT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3668
|
+
var SUBMIT_RETRY_INTERVAL_MS2 = 1e3;
|
|
3503
3669
|
function assertDecryptSubmitResponseV2(value) {
|
|
3504
3670
|
if (value == null || typeof value !== "object") {
|
|
3505
3671
|
throw new CofheError({
|
|
@@ -3511,16 +3677,65 @@ function assertDecryptSubmitResponseV2(value) {
|
|
|
3511
3677
|
});
|
|
3512
3678
|
}
|
|
3513
3679
|
const v = value;
|
|
3514
|
-
if (
|
|
3680
|
+
if (v.request_id !== null && typeof v.request_id !== "string") {
|
|
3515
3681
|
throw new CofheError({
|
|
3516
3682
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3517
|
-
message: "decrypt submit response
|
|
3683
|
+
message: "decrypt submit response has invalid request_id",
|
|
3518
3684
|
context: {
|
|
3519
3685
|
value
|
|
3520
3686
|
}
|
|
3521
3687
|
});
|
|
3522
3688
|
}
|
|
3523
|
-
return {
|
|
3689
|
+
return {
|
|
3690
|
+
request_id: v.request_id ?? null,
|
|
3691
|
+
status: typeof v.status === "string" ? v.status : void 0,
|
|
3692
|
+
is_succeed: typeof v.is_succeed === "boolean" ? v.is_succeed : void 0,
|
|
3693
|
+
decrypted: Array.isArray(v.decrypted) ? v.decrypted : void 0,
|
|
3694
|
+
signature: typeof v.signature === "string" ? v.signature : void 0,
|
|
3695
|
+
encryption_type: typeof v.encryption_type === "number" ? v.encryption_type : void 0,
|
|
3696
|
+
error_message: typeof v.error_message === "string" || v.error_message === null ? v.error_message : void 0,
|
|
3697
|
+
message: typeof v.message === "string" ? v.message : void 0
|
|
3698
|
+
};
|
|
3699
|
+
}
|
|
3700
|
+
function parseCompletedDecryptResponseV2(params) {
|
|
3701
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
3702
|
+
if (value.is_succeed === false) {
|
|
3703
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
3704
|
+
throw new CofheError({
|
|
3705
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3706
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3707
|
+
context: {
|
|
3708
|
+
thresholdNetworkUrl,
|
|
3709
|
+
requestId,
|
|
3710
|
+
response: value
|
|
3711
|
+
}
|
|
3712
|
+
});
|
|
3713
|
+
}
|
|
3714
|
+
if (value.error_message) {
|
|
3715
|
+
throw new CofheError({
|
|
3716
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3717
|
+
message: `decrypt request failed: ${value.error_message}`,
|
|
3718
|
+
context: {
|
|
3719
|
+
thresholdNetworkUrl,
|
|
3720
|
+
requestId,
|
|
3721
|
+
response: value
|
|
3722
|
+
}
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
if (!Array.isArray(value.decrypted)) {
|
|
3726
|
+
throw new CofheError({
|
|
3727
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3728
|
+
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3729
|
+
context: {
|
|
3730
|
+
thresholdNetworkUrl,
|
|
3731
|
+
requestId,
|
|
3732
|
+
response: value
|
|
3733
|
+
}
|
|
3734
|
+
});
|
|
3735
|
+
}
|
|
3736
|
+
const decryptedValue = parseDecryptedBytesToBigInt(value.decrypted);
|
|
3737
|
+
const signature = normalizeTnSignature(value.signature);
|
|
3738
|
+
return { decryptedValue, signature };
|
|
3524
3739
|
}
|
|
3525
3740
|
function assertDecryptStatusResponseV2(value) {
|
|
3526
3741
|
if (value == null || typeof value !== "object") {
|
|
@@ -3566,7 +3781,7 @@ function assertDecryptStatusResponseV2(value) {
|
|
|
3566
3781
|
}
|
|
3567
3782
|
return value;
|
|
3568
3783
|
}
|
|
3569
|
-
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission) {
|
|
3784
|
+
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
3570
3785
|
const body = {
|
|
3571
3786
|
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3572
3787
|
host_chain_id: chainId
|
|
@@ -3574,79 +3789,151 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
3574
3789
|
if (permission) {
|
|
3575
3790
|
body.permit = permission;
|
|
3576
3791
|
}
|
|
3577
|
-
let
|
|
3578
|
-
|
|
3579
|
-
response
|
|
3580
|
-
method: "POST",
|
|
3581
|
-
headers: {
|
|
3582
|
-
"Content-Type": "application/json"
|
|
3583
|
-
},
|
|
3584
|
-
body: JSON.stringify(body)
|
|
3585
|
-
});
|
|
3586
|
-
} catch (e) {
|
|
3587
|
-
throw new CofheError({
|
|
3588
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3589
|
-
message: `decrypt request failed`,
|
|
3590
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3591
|
-
cause: e instanceof Error ? e : void 0,
|
|
3592
|
-
context: {
|
|
3593
|
-
thresholdNetworkUrl,
|
|
3594
|
-
body
|
|
3595
|
-
}
|
|
3596
|
-
});
|
|
3597
|
-
}
|
|
3598
|
-
if (!response.ok) {
|
|
3599
|
-
let errorMessage = `HTTP ${response.status}`;
|
|
3792
|
+
let attemptIndex = 0;
|
|
3793
|
+
for (; ; ) {
|
|
3794
|
+
let response;
|
|
3600
3795
|
try {
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3796
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
|
|
3797
|
+
method: "POST",
|
|
3798
|
+
headers: {
|
|
3799
|
+
"Content-Type": "application/json"
|
|
3800
|
+
},
|
|
3801
|
+
body: JSON.stringify(body)
|
|
3802
|
+
});
|
|
3803
|
+
} catch (e) {
|
|
3804
|
+
throw new CofheError({
|
|
3805
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3806
|
+
message: `decrypt request failed`,
|
|
3807
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3808
|
+
cause: e instanceof Error ? e : void 0,
|
|
3809
|
+
context: {
|
|
3810
|
+
thresholdNetworkUrl,
|
|
3811
|
+
body,
|
|
3812
|
+
attemptIndex
|
|
3813
|
+
}
|
|
3814
|
+
});
|
|
3607
3815
|
}
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3816
|
+
if (!response.ok) {
|
|
3817
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
3818
|
+
try {
|
|
3819
|
+
const errorBody = await response.json();
|
|
3820
|
+
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
3821
|
+
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
3822
|
+
errorMessage = maybeMessage;
|
|
3823
|
+
} catch {
|
|
3824
|
+
errorMessage = response.statusText || errorMessage;
|
|
3617
3825
|
}
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3826
|
+
throw new CofheError({
|
|
3827
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3828
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3829
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3830
|
+
context: {
|
|
3831
|
+
thresholdNetworkUrl,
|
|
3832
|
+
status: response.status,
|
|
3833
|
+
statusText: response.statusText,
|
|
3834
|
+
body,
|
|
3835
|
+
attemptIndex
|
|
3836
|
+
}
|
|
3837
|
+
});
|
|
3838
|
+
}
|
|
3839
|
+
let submitResponse;
|
|
3840
|
+
if (response.status !== 204) {
|
|
3841
|
+
let rawJson;
|
|
3842
|
+
try {
|
|
3843
|
+
rawJson = await response.json();
|
|
3844
|
+
} catch (e) {
|
|
3845
|
+
throw new CofheError({
|
|
3846
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3847
|
+
message: `Failed to parse decrypt submit response`,
|
|
3848
|
+
cause: e instanceof Error ? e : void 0,
|
|
3849
|
+
context: {
|
|
3850
|
+
thresholdNetworkUrl,
|
|
3851
|
+
body,
|
|
3852
|
+
attemptIndex
|
|
3853
|
+
}
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3856
|
+
submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3857
|
+
if (Array.isArray(submitResponse.decrypted) && typeof submitResponse.signature === "string") {
|
|
3858
|
+
return {
|
|
3859
|
+
kind: "completed",
|
|
3860
|
+
...parseCompletedDecryptResponseV2({
|
|
3861
|
+
value: submitResponse,
|
|
3862
|
+
thresholdNetworkUrl,
|
|
3863
|
+
requestId: submitResponse.request_id
|
|
3864
|
+
})
|
|
3865
|
+
};
|
|
3866
|
+
}
|
|
3867
|
+
if (submitResponse.request_id) {
|
|
3868
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
3869
|
+
}
|
|
3870
|
+
}
|
|
3871
|
+
if (response.status === 204) {
|
|
3872
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3873
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3874
|
+
throw new CofheError({
|
|
3875
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3876
|
+
message: `decrypt submit retried without receiving request_id for ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3877
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
3878
|
+
context: {
|
|
3879
|
+
thresholdNetworkUrl,
|
|
3880
|
+
body,
|
|
3881
|
+
attemptIndex,
|
|
3882
|
+
timeoutMs: DECRYPT_TIMEOUT_MS,
|
|
3883
|
+
submitResponse,
|
|
3884
|
+
status: response.status
|
|
3885
|
+
}
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3888
|
+
onPoll?.({
|
|
3889
|
+
operation: "decrypt",
|
|
3890
|
+
requestId: "",
|
|
3891
|
+
attemptIndex,
|
|
3892
|
+
elapsedMs,
|
|
3893
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS2,
|
|
3894
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3895
|
+
});
|
|
3896
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS2));
|
|
3897
|
+
attemptIndex += 1;
|
|
3898
|
+
continue;
|
|
3899
|
+
}
|
|
3624
3900
|
throw new CofheError({
|
|
3625
3901
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3626
|
-
message: `
|
|
3627
|
-
cause: e instanceof Error ? e : void 0,
|
|
3902
|
+
message: `decrypt submit response missing request_id`,
|
|
3628
3903
|
context: {
|
|
3629
3904
|
thresholdNetworkUrl,
|
|
3630
|
-
body
|
|
3905
|
+
body,
|
|
3906
|
+
submitResponse,
|
|
3907
|
+
attemptIndex
|
|
3631
3908
|
}
|
|
3632
3909
|
});
|
|
3633
3910
|
}
|
|
3634
|
-
const submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3635
|
-
return submitResponse.request_id;
|
|
3636
3911
|
}
|
|
3637
|
-
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3912
|
+
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
3913
|
+
let attemptIndex = 0;
|
|
3914
|
+
while (true) {
|
|
3915
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3916
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3917
|
+
minIntervalMs: POLL_INTERVAL_MS2,
|
|
3918
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS2
|
|
3919
|
+
});
|
|
3920
|
+
onPoll?.({
|
|
3921
|
+
operation: "decrypt",
|
|
3922
|
+
requestId,
|
|
3923
|
+
attemptIndex,
|
|
3924
|
+
elapsedMs,
|
|
3925
|
+
intervalMs,
|
|
3926
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3927
|
+
});
|
|
3928
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3642
3929
|
throw new CofheError({
|
|
3643
3930
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3644
|
-
message: `decrypt polling timed out after ${
|
|
3931
|
+
message: `decrypt polling timed out after ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3645
3932
|
hint: "The request may still be processing. Try again later.",
|
|
3646
3933
|
context: {
|
|
3647
3934
|
thresholdNetworkUrl,
|
|
3648
3935
|
requestId,
|
|
3649
|
-
timeoutMs:
|
|
3936
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3650
3937
|
}
|
|
3651
3938
|
});
|
|
3652
3939
|
}
|
|
@@ -3718,45 +4005,14 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3718
4005
|
}
|
|
3719
4006
|
const statusResponse = assertDecryptStatusResponseV2(rawJson);
|
|
3720
4007
|
if (statusResponse.status === "COMPLETED") {
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
context: {
|
|
3727
|
-
thresholdNetworkUrl,
|
|
3728
|
-
requestId,
|
|
3729
|
-
statusResponse
|
|
3730
|
-
}
|
|
3731
|
-
});
|
|
3732
|
-
}
|
|
3733
|
-
if (statusResponse.error_message) {
|
|
3734
|
-
throw new CofheError({
|
|
3735
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3736
|
-
message: `decrypt request failed: ${statusResponse.error_message}`,
|
|
3737
|
-
context: {
|
|
3738
|
-
thresholdNetworkUrl,
|
|
3739
|
-
requestId,
|
|
3740
|
-
statusResponse
|
|
3741
|
-
}
|
|
3742
|
-
});
|
|
3743
|
-
}
|
|
3744
|
-
if (!Array.isArray(statusResponse.decrypted)) {
|
|
3745
|
-
throw new CofheError({
|
|
3746
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3747
|
-
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3748
|
-
context: {
|
|
3749
|
-
thresholdNetworkUrl,
|
|
3750
|
-
requestId,
|
|
3751
|
-
statusResponse
|
|
3752
|
-
}
|
|
3753
|
-
});
|
|
3754
|
-
}
|
|
3755
|
-
const decryptedValue = parseDecryptedBytesToBigInt(statusResponse.decrypted);
|
|
3756
|
-
const signature = normalizeTnSignature(statusResponse.signature);
|
|
3757
|
-
return { decryptedValue, signature };
|
|
4008
|
+
return parseCompletedDecryptResponseV2({
|
|
4009
|
+
value: statusResponse,
|
|
4010
|
+
thresholdNetworkUrl,
|
|
4011
|
+
requestId
|
|
4012
|
+
});
|
|
3758
4013
|
}
|
|
3759
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
4014
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
4015
|
+
attemptIndex += 1;
|
|
3760
4016
|
}
|
|
3761
4017
|
throw new CofheError({
|
|
3762
4018
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
@@ -3767,9 +4023,21 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3767
4023
|
}
|
|
3768
4024
|
});
|
|
3769
4025
|
}
|
|
3770
|
-
async function tnDecryptV2(
|
|
3771
|
-
const
|
|
3772
|
-
|
|
4026
|
+
async function tnDecryptV2(params) {
|
|
4027
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
4028
|
+
const overallStartTime = Date.now();
|
|
4029
|
+
const submitResult = await submitDecryptRequestV2(
|
|
4030
|
+
thresholdNetworkUrl,
|
|
4031
|
+
ctHash,
|
|
4032
|
+
chainId,
|
|
4033
|
+
permission,
|
|
4034
|
+
overallStartTime,
|
|
4035
|
+
onPoll
|
|
4036
|
+
);
|
|
4037
|
+
if (submitResult.kind === "completed") {
|
|
4038
|
+
return submitResult;
|
|
4039
|
+
}
|
|
4040
|
+
return await pollDecryptStatusV2(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
3773
4041
|
}
|
|
3774
4042
|
|
|
3775
4043
|
// core/decrypt/decryptForTxBuilder.ts
|
|
@@ -3778,6 +4046,7 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3778
4046
|
permitHash;
|
|
3779
4047
|
permit;
|
|
3780
4048
|
permitSelection = "unset";
|
|
4049
|
+
pollCallback;
|
|
3781
4050
|
constructor(params) {
|
|
3782
4051
|
super({
|
|
3783
4052
|
config: params.config,
|
|
@@ -3803,6 +4072,10 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3803
4072
|
getAccount() {
|
|
3804
4073
|
return this.account;
|
|
3805
4074
|
}
|
|
4075
|
+
onPoll(callback) {
|
|
4076
|
+
this.pollCallback = callback;
|
|
4077
|
+
return this;
|
|
4078
|
+
}
|
|
3806
4079
|
withPermit(permitOrPermitHash) {
|
|
3807
4080
|
if (this.permitSelection === "with-permit") {
|
|
3808
4081
|
throw new CofheError({
|
|
@@ -3930,7 +4203,13 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3930
4203
|
this.assertPublicClient();
|
|
3931
4204
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3932
4205
|
const permission = permit ? PermitUtils.getPermission(permit, true) : null;
|
|
3933
|
-
const { decryptedValue, signature } = await tnDecryptV2(
|
|
4206
|
+
const { decryptedValue, signature } = await tnDecryptV2({
|
|
4207
|
+
ctHash: this.ctHash,
|
|
4208
|
+
chainId: this.chainId,
|
|
4209
|
+
permission,
|
|
4210
|
+
thresholdNetworkUrl,
|
|
4211
|
+
onPoll: this.pollCallback
|
|
4212
|
+
});
|
|
3934
4213
|
return {
|
|
3935
4214
|
ctHash: this.ctHash,
|
|
3936
4215
|
decryptedValue,
|
|
@@ -3948,7 +4227,6 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3948
4227
|
const permit = await this.getResolvedPermit();
|
|
3949
4228
|
if (permit !== null) {
|
|
3950
4229
|
PermitUtils.validate(permit);
|
|
3951
|
-
PermitUtils.isValid(permit);
|
|
3952
4230
|
const chainId = permit._signedDomain.chainId;
|
|
3953
4231
|
if (chainId === hardhat2.id) {
|
|
3954
4232
|
return await this.mocksDecryptForTx(permit);
|
|
@@ -3969,6 +4247,35 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3969
4247
|
}
|
|
3970
4248
|
}
|
|
3971
4249
|
};
|
|
4250
|
+
var decryptResultSignerAbi = viem.parseAbi(["function decryptResultSigner() view returns (address)"]);
|
|
4251
|
+
var UINT_TYPE_MASK2 = 0x7fn;
|
|
4252
|
+
var TYPE_BYTE_OFFSET2 = 8n;
|
|
4253
|
+
var getEncryptionTypeFromCtHash2 = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET2 & UINT_TYPE_MASK2);
|
|
4254
|
+
var buildDecryptResultHash = (ctHash, cleartext, chainId) => {
|
|
4255
|
+
const encryptionType = getEncryptionTypeFromCtHash2(ctHash);
|
|
4256
|
+
return viem.keccak256(
|
|
4257
|
+
viem.encodePacked(["uint256", "uint32", "uint64", "uint256"], [cleartext, encryptionType, BigInt(chainId), ctHash])
|
|
4258
|
+
);
|
|
4259
|
+
};
|
|
4260
|
+
async function verifyDecryptResult(handle, cleartext, signature, publicClient) {
|
|
4261
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
4262
|
+
const expectedSigner = await publicClient.readContract({
|
|
4263
|
+
address: TASK_MANAGER_ADDRESS,
|
|
4264
|
+
abi: decryptResultSignerAbi,
|
|
4265
|
+
functionName: "decryptResultSigner",
|
|
4266
|
+
args: []
|
|
4267
|
+
});
|
|
4268
|
+
if (viem.isAddressEqual(expectedSigner, viem.zeroAddress))
|
|
4269
|
+
return true;
|
|
4270
|
+
const ctHash = BigInt(handle);
|
|
4271
|
+
const messageHash = buildDecryptResultHash(ctHash, cleartext, chainId);
|
|
4272
|
+
try {
|
|
4273
|
+
const recovered = await viem.recoverAddress({ hash: messageHash, signature });
|
|
4274
|
+
return viem.isAddressEqual(recovered, expectedSigner);
|
|
4275
|
+
} catch {
|
|
4276
|
+
return false;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
3972
4279
|
|
|
3973
4280
|
// core/client.ts
|
|
3974
4281
|
var InitialConnectStore = {
|
|
@@ -4087,6 +4394,11 @@ function createCofheClientBase(opts) {
|
|
|
4087
4394
|
requireConnected: _requireConnected
|
|
4088
4395
|
});
|
|
4089
4396
|
}
|
|
4397
|
+
function verifyDecryptResult2(handle, cleartext, signature) {
|
|
4398
|
+
_requireConnected();
|
|
4399
|
+
const { publicClient } = connectStore.getState();
|
|
4400
|
+
return verifyDecryptResult(handle, cleartext, signature, publicClient);
|
|
4401
|
+
}
|
|
4090
4402
|
const _getChainIdAndAccount = (chainId, account) => {
|
|
4091
4403
|
const state = connectStore.getState();
|
|
4092
4404
|
const _chainId = chainId ?? state.chainId;
|
|
@@ -4169,6 +4481,7 @@ function createCofheClientBase(opts) {
|
|
|
4169
4481
|
},
|
|
4170
4482
|
// Utils (no context needed)
|
|
4171
4483
|
getHash: permits.getHash,
|
|
4484
|
+
export: permits.export,
|
|
4172
4485
|
serialize: permits.serialize,
|
|
4173
4486
|
deserialize: permits.deserialize
|
|
4174
4487
|
};
|
|
@@ -4197,6 +4510,7 @@ function createCofheClientBase(opts) {
|
|
|
4197
4510
|
*/
|
|
4198
4511
|
decryptHandle: decryptForView,
|
|
4199
4512
|
decryptForTx,
|
|
4513
|
+
verifyDecryptResult: verifyDecryptResult2,
|
|
4200
4514
|
permits: clientPermits
|
|
4201
4515
|
// Add SDK-specific methods below that require connection
|
|
4202
4516
|
// Example:
|
|
@@ -4225,6 +4539,8 @@ exports.MOCKS_ZK_VERIFIER_SIGNER_ADDRESS = MOCKS_ZK_VERIFIER_SIGNER_ADDRESS;
|
|
|
4225
4539
|
exports.MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY;
|
|
4226
4540
|
exports.TASK_MANAGER_ADDRESS = TASK_MANAGER_ADDRESS;
|
|
4227
4541
|
exports.TEST_BED_ADDRESS = TEST_BED_ADDRESS;
|
|
4542
|
+
exports.TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT;
|
|
4543
|
+
exports.TFHE_RS_ZK_MAX_BITS = TFHE_RS_ZK_MAX_BITS;
|
|
4228
4544
|
exports.assertCorrectEncryptedItemInput = assertCorrectEncryptedItemInput;
|
|
4229
4545
|
exports.createCofheClientBase = createCofheClientBase;
|
|
4230
4546
|
exports.createCofheConfigBase = createCofheConfigBase;
|
|
@@ -4235,4 +4551,5 @@ exports.getCofheConfigItem = getCofheConfigItem;
|
|
|
4235
4551
|
exports.isCofheError = isCofheError;
|
|
4236
4552
|
exports.isEncryptableItem = isEncryptableItem;
|
|
4237
4553
|
exports.isLastEncryptionStep = isLastEncryptionStep;
|
|
4554
|
+
exports.verifyDecryptResult = verifyDecryptResult;
|
|
4238
4555
|
exports.zkProveWithWorker = zkProveWithWorker;
|