@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/node.cjs
CHANGED
|
@@ -12,25 +12,9 @@ var fs = require('fs');
|
|
|
12
12
|
var path = require('path');
|
|
13
13
|
var nodeTfhe = require('node-tfhe');
|
|
14
14
|
|
|
15
|
-
function
|
|
16
|
-
if (e && e.__esModule) return e;
|
|
17
|
-
var n = Object.create(null);
|
|
18
|
-
if (e) {
|
|
19
|
-
Object.keys(e).forEach(function (k) {
|
|
20
|
-
if (k !== 'default') {
|
|
21
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
22
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
23
|
-
enumerable: true,
|
|
24
|
-
get: function () { return e[k]; }
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
n.default = e;
|
|
30
|
-
return Object.freeze(n);
|
|
31
|
-
}
|
|
15
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
32
16
|
|
|
33
|
-
var
|
|
17
|
+
var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
34
18
|
|
|
35
19
|
// core/client.ts
|
|
36
20
|
|
|
@@ -123,6 +107,16 @@ var bigintSafeJsonStringify = (value) => {
|
|
|
123
107
|
};
|
|
124
108
|
var isCofheError = (error) => error instanceof CofheError;
|
|
125
109
|
|
|
110
|
+
// core/consts.ts
|
|
111
|
+
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
112
|
+
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
113
|
+
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
114
|
+
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
115
|
+
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
116
|
+
var TFHE_RS_ZK_MAX_BITS = 2048;
|
|
117
|
+
var TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = BigInt(1 << 30);
|
|
118
|
+
var TFHE_RS_KEY_VERSION = 2;
|
|
119
|
+
|
|
126
120
|
// core/types.ts
|
|
127
121
|
var FheUintUTypes = [
|
|
128
122
|
2 /* Uint8 */,
|
|
@@ -209,7 +203,6 @@ var MAX_UINT32 = 4294967295n;
|
|
|
209
203
|
var MAX_UINT64 = 18446744073709551615n;
|
|
210
204
|
var MAX_UINT128 = 340282366920938463463374607431768211455n;
|
|
211
205
|
var MAX_UINT160 = 1461501637330902918203684832716283019655932542975n;
|
|
212
|
-
var MAX_ENCRYPTABLE_BITS = 2048;
|
|
213
206
|
var zkPack = (items, builder) => {
|
|
214
207
|
let totalBits = 0;
|
|
215
208
|
for (const item of items) {
|
|
@@ -273,14 +266,14 @@ var zkPack = (items, builder) => {
|
|
|
273
266
|
}
|
|
274
267
|
}
|
|
275
268
|
}
|
|
276
|
-
if (totalBits >
|
|
269
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
277
270
|
throw new CofheError({
|
|
278
271
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
279
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
280
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
272
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
273
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
281
274
|
context: {
|
|
282
275
|
totalBits,
|
|
283
|
-
maxBits:
|
|
276
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
284
277
|
items
|
|
285
278
|
}
|
|
286
279
|
});
|
|
@@ -299,7 +292,7 @@ var zkProve = async (builder, crs, metadata) => {
|
|
|
299
292
|
1
|
|
300
293
|
// ZkComputeLoad.Verify
|
|
301
294
|
);
|
|
302
|
-
resolve(compactList.
|
|
295
|
+
resolve(compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT));
|
|
303
296
|
}, 0);
|
|
304
297
|
});
|
|
305
298
|
};
|
|
@@ -475,15 +468,6 @@ var MockZkVerifierAbi = [
|
|
|
475
468
|
},
|
|
476
469
|
{ type: "error", name: "InvalidInputs", inputs: [] }
|
|
477
470
|
];
|
|
478
|
-
|
|
479
|
-
// core/consts.ts
|
|
480
|
-
var TASK_MANAGER_ADDRESS = "0xeA30c4B8b44078Bbf8a6ef5b9f1eC1626C7848D9";
|
|
481
|
-
var MOCKS_ZK_VERIFIER_ADDRESS = "0x0000000000000000000000000000000000005001";
|
|
482
|
-
var MOCKS_THRESHOLD_NETWORK_ADDRESS = "0x0000000000000000000000000000000000005002";
|
|
483
|
-
var MOCKS_ZK_VERIFIER_SIGNER_PRIVATE_KEY = "0x6C8D7F768A6BB4AAFE85E8A2F5A9680355239C7E14646ED62B044E39DE154512";
|
|
484
|
-
var MOCKS_DECRYPT_RESULT_SIGNER_PRIVATE_KEY = "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
|
|
485
|
-
|
|
486
|
-
// core/encrypt/cofheMocksZkVerifySign.ts
|
|
487
471
|
function createMockZkVerifierSigner() {
|
|
488
472
|
return viem.createWalletClient({
|
|
489
473
|
chain: chains.hardhat,
|
|
@@ -525,14 +509,14 @@ async function cofheMocksCheckEncryptableBits(items) {
|
|
|
525
509
|
}
|
|
526
510
|
}
|
|
527
511
|
}
|
|
528
|
-
if (totalBits >
|
|
512
|
+
if (totalBits > TFHE_RS_ZK_MAX_BITS) {
|
|
529
513
|
throw new CofheError({
|
|
530
514
|
code: "ZK_PACK_FAILED" /* ZkPackFailed */,
|
|
531
|
-
message: `Total bits ${totalBits} exceeds ${
|
|
532
|
-
hint: `Ensure that the total bits of the items to encrypt does not exceed ${
|
|
515
|
+
message: `Total bits ${totalBits} exceeds ${TFHE_RS_ZK_MAX_BITS}`,
|
|
516
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${TFHE_RS_ZK_MAX_BITS}`,
|
|
533
517
|
context: {
|
|
534
518
|
totalBits,
|
|
535
|
-
maxBits:
|
|
519
|
+
maxBits: TFHE_RS_ZK_MAX_BITS,
|
|
536
520
|
items
|
|
537
521
|
}
|
|
538
522
|
});
|
|
@@ -803,6 +787,7 @@ function getThresholdNetworkUrlOrThrow(config, chainId) {
|
|
|
803
787
|
}
|
|
804
788
|
return url;
|
|
805
789
|
}
|
|
790
|
+
var KEYSTORE_NAME = `cofhesdk-keys-v${TFHE_RS_KEY_VERSION}`;
|
|
806
791
|
function isValidPersistedState(state) {
|
|
807
792
|
if (state && typeof state === "object") {
|
|
808
793
|
if ("fhe" in state && "crs" in state) {
|
|
@@ -857,7 +842,7 @@ function createKeysStore(storage) {
|
|
|
857
842
|
};
|
|
858
843
|
const clearKeysStorage = async () => {
|
|
859
844
|
if (storage) {
|
|
860
|
-
await storage.removeItem(
|
|
845
|
+
await storage.removeItem(KEYSTORE_NAME);
|
|
861
846
|
}
|
|
862
847
|
};
|
|
863
848
|
const rehydrateKeysStore = async () => {
|
|
@@ -887,7 +872,7 @@ function createStoreWithPersit(storage) {
|
|
|
887
872
|
if (_error)
|
|
888
873
|
throw new Error(`onRehydrateStorage: Error rehydrating keys store: ${_error}`);
|
|
889
874
|
},
|
|
890
|
-
name:
|
|
875
|
+
name: KEYSTORE_NAME,
|
|
891
876
|
storage: middleware.createJSONStorage(() => storage),
|
|
892
877
|
merge: (persistedState, currentState) => {
|
|
893
878
|
const persisted = isValidPersistedState(persistedState) ? persistedState : DEFAULT_KEYS_STORE;
|
|
@@ -1612,7 +1597,7 @@ var SealingKey = class _SealingKey {
|
|
|
1612
1597
|
const ephemPublicKey = parsedData.public_key instanceof Uint8Array ? parsedData.public_key : new Uint8Array(parsedData.public_key);
|
|
1613
1598
|
const dataToDecrypt = parsedData.data instanceof Uint8Array ? parsedData.data : new Uint8Array(parsedData.data);
|
|
1614
1599
|
const privateKeyBytes = fromHexString(this.privateKey);
|
|
1615
|
-
const decryptedMessage =
|
|
1600
|
+
const decryptedMessage = nacl__default.default.box.open(dataToDecrypt, nonce, ephemPublicKey, privateKeyBytes);
|
|
1616
1601
|
if (!decryptedMessage) {
|
|
1617
1602
|
throw new Error("Failed to decrypt message");
|
|
1618
1603
|
}
|
|
@@ -1645,9 +1630,9 @@ var SealingKey = class _SealingKey {
|
|
|
1645
1630
|
static seal = (value, publicKey) => {
|
|
1646
1631
|
isString(publicKey);
|
|
1647
1632
|
isBigIntOrNumber(value);
|
|
1648
|
-
const ephemeralKeyPair =
|
|
1649
|
-
const nonce =
|
|
1650
|
-
const encryptedMessage =
|
|
1633
|
+
const ephemeralKeyPair = nacl__default.default.box.keyPair();
|
|
1634
|
+
const nonce = nacl__default.default.randomBytes(nacl__default.default.box.nonceLength);
|
|
1635
|
+
const encryptedMessage = nacl__default.default.box(toBeArray(value), nonce, fromHexString(publicKey), ephemeralKeyPair.secretKey);
|
|
1651
1636
|
return {
|
|
1652
1637
|
data: encryptedMessage,
|
|
1653
1638
|
public_key: ephemeralKeyPair.publicKey,
|
|
@@ -1656,7 +1641,7 @@ var SealingKey = class _SealingKey {
|
|
|
1656
1641
|
};
|
|
1657
1642
|
};
|
|
1658
1643
|
var GenerateSealingKey = () => {
|
|
1659
|
-
const sodiumKeypair =
|
|
1644
|
+
const sodiumKeypair = nacl__default.default.box.keyPair();
|
|
1660
1645
|
return new SealingKey(toHexString2(sodiumKeypair.secretKey), toHexString2(sodiumKeypair.publicKey));
|
|
1661
1646
|
};
|
|
1662
1647
|
var SerializedSealingPair = zod.z.object({
|
|
@@ -1814,9 +1799,9 @@ var ValidationUtils = {
|
|
|
1814
1799
|
return false;
|
|
1815
1800
|
},
|
|
1816
1801
|
/**
|
|
1817
|
-
*
|
|
1802
|
+
* Checks that a permit is signed and not expired.
|
|
1818
1803
|
*/
|
|
1819
|
-
|
|
1804
|
+
isSignedAndNotExpired: (permit) => {
|
|
1820
1805
|
if (ValidationUtils.isExpired(permit)) {
|
|
1821
1806
|
return { valid: false, error: "expired" };
|
|
1822
1807
|
}
|
|
@@ -1824,6 +1809,34 @@ var ValidationUtils = {
|
|
|
1824
1809
|
return { valid: false, error: "not-signed" };
|
|
1825
1810
|
}
|
|
1826
1811
|
return { valid: true, error: null };
|
|
1812
|
+
},
|
|
1813
|
+
/**
|
|
1814
|
+
* Asserts that a permit is signed and not expired.
|
|
1815
|
+
*
|
|
1816
|
+
* Throws `Error` with message:
|
|
1817
|
+
* - `Permit is expired`
|
|
1818
|
+
* - `Permit is not signed`
|
|
1819
|
+
*/
|
|
1820
|
+
assertSignedAndNotExpired: (permit) => {
|
|
1821
|
+
const result = ValidationUtils.isSignedAndNotExpired(permit);
|
|
1822
|
+
if (result.valid)
|
|
1823
|
+
return;
|
|
1824
|
+
if (result.error === "expired") {
|
|
1825
|
+
throw new Error("Permit is expired");
|
|
1826
|
+
}
|
|
1827
|
+
if (result.error === "not-signed") {
|
|
1828
|
+
throw new Error("Permit is not signed");
|
|
1829
|
+
}
|
|
1830
|
+
throw new Error("Permit is invalid");
|
|
1831
|
+
},
|
|
1832
|
+
isValid: (permit) => {
|
|
1833
|
+
const schema = permit.type === "self" ? SelfPermitValidator : permit.type === "sharing" ? SharingPermitValidator : permit.type === "recipient" ? ImportPermitValidator : null;
|
|
1834
|
+
if (schema == null)
|
|
1835
|
+
return { valid: false, error: "invalid-schema" };
|
|
1836
|
+
const schemaResult = schema.safeParse(permit);
|
|
1837
|
+
if (!schemaResult.success)
|
|
1838
|
+
return { valid: false, error: "invalid-schema" };
|
|
1839
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
1827
1840
|
}
|
|
1828
1841
|
};
|
|
1829
1842
|
|
|
@@ -2205,9 +2218,9 @@ var PermitUtils = {
|
|
|
2205
2218
|
};
|
|
2206
2219
|
},
|
|
2207
2220
|
/**
|
|
2208
|
-
* Validate a permit
|
|
2221
|
+
* Validate a permit (schema-level validation)
|
|
2209
2222
|
*/
|
|
2210
|
-
|
|
2223
|
+
validateSchema: (permit) => {
|
|
2211
2224
|
if (permit.type === "self") {
|
|
2212
2225
|
return validateSelfPermit(permit);
|
|
2213
2226
|
} else if (permit.type === "sharing") {
|
|
@@ -2218,12 +2231,27 @@ var PermitUtils = {
|
|
|
2218
2231
|
throw new Error("Invalid permit type");
|
|
2219
2232
|
}
|
|
2220
2233
|
},
|
|
2234
|
+
/**
|
|
2235
|
+
* Validate a permit (holistic validation).
|
|
2236
|
+
*
|
|
2237
|
+
* This validates:
|
|
2238
|
+
* - Permit schema (shape + invariants)
|
|
2239
|
+
* - Permit is signed
|
|
2240
|
+
* - Permit is not expired
|
|
2241
|
+
*
|
|
2242
|
+
* For schema-only validation, use `validateSchema(permit)`.
|
|
2243
|
+
*/
|
|
2244
|
+
validate: (permit) => {
|
|
2245
|
+
const validated = PermitUtils.validateSchema(permit);
|
|
2246
|
+
ValidationUtils.assertSignedAndNotExpired(validated);
|
|
2247
|
+
return validated;
|
|
2248
|
+
},
|
|
2221
2249
|
/**
|
|
2222
2250
|
* Get the permission object from a permit (for use in contracts)
|
|
2223
2251
|
*/
|
|
2224
2252
|
getPermission: (permit, skipValidation = false) => {
|
|
2225
2253
|
if (!skipValidation) {
|
|
2226
|
-
PermitUtils.
|
|
2254
|
+
PermitUtils.validateSchema(permit);
|
|
2227
2255
|
}
|
|
2228
2256
|
return {
|
|
2229
2257
|
issuer: permit.issuer,
|
|
@@ -2289,8 +2317,17 @@ var PermitUtils = {
|
|
|
2289
2317
|
return ValidationUtils.isSigned(permit);
|
|
2290
2318
|
},
|
|
2291
2319
|
/**
|
|
2292
|
-
* Check if permit is
|
|
2320
|
+
* Check if permit is signed and not expired
|
|
2293
2321
|
*/
|
|
2322
|
+
isSignedAndNotExpired: (permit) => {
|
|
2323
|
+
return ValidationUtils.isSignedAndNotExpired(permit);
|
|
2324
|
+
},
|
|
2325
|
+
/**
|
|
2326
|
+
* Assert that permit is signed and not expired
|
|
2327
|
+
*/
|
|
2328
|
+
assertSignedAndNotExpired: (permit) => {
|
|
2329
|
+
return ValidationUtils.assertSignedAndNotExpired(permit);
|
|
2330
|
+
},
|
|
2294
2331
|
isValid: (permit) => {
|
|
2295
2332
|
return ValidationUtils.isValid(permit);
|
|
2296
2333
|
},
|
|
@@ -2468,6 +2505,9 @@ var importShared = async (options, publicClient, walletClient) => {
|
|
|
2468
2505
|
var getHash = (permit) => {
|
|
2469
2506
|
return PermitUtils.getHash(permit);
|
|
2470
2507
|
};
|
|
2508
|
+
var exportShared = (permit) => {
|
|
2509
|
+
return PermitUtils.export(permit);
|
|
2510
|
+
};
|
|
2471
2511
|
var serialize = (permit) => {
|
|
2472
2512
|
return PermitUtils.serialize(permit);
|
|
2473
2513
|
};
|
|
@@ -2518,6 +2558,7 @@ var permits = {
|
|
|
2518
2558
|
getOrCreateSelfPermit,
|
|
2519
2559
|
getOrCreateSharingPermit,
|
|
2520
2560
|
getHash,
|
|
2561
|
+
export: exportShared,
|
|
2521
2562
|
serialize,
|
|
2522
2563
|
deserialize,
|
|
2523
2564
|
getPermit: getPermit2,
|
|
@@ -2760,9 +2801,19 @@ async function cofheMocksDecryptForView(ctHash, utype, permit, publicClient) {
|
|
|
2760
2801
|
return unsealed;
|
|
2761
2802
|
}
|
|
2762
2803
|
|
|
2804
|
+
// core/decrypt/polling.ts
|
|
2805
|
+
function computeMinuteRampPollIntervalMs(elapsedMs, params) {
|
|
2806
|
+
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
|
2807
|
+
const intervalSeconds = 1 + Math.floor(elapsedSeconds / 60);
|
|
2808
|
+
const intervalMs = intervalSeconds * 1e3;
|
|
2809
|
+
return Math.min(params.maxIntervalMs, Math.max(params.minIntervalMs, intervalMs));
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2763
2812
|
// core/decrypt/tnSealOutputV2.ts
|
|
2764
2813
|
var POLL_INTERVAL_MS = 1e3;
|
|
2765
|
-
var
|
|
2814
|
+
var POLL_MAX_INTERVAL_MS = 1e4;
|
|
2815
|
+
var SEAL_OUTPUT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2816
|
+
var SUBMIT_RETRY_INTERVAL_MS = 1e3;
|
|
2766
2817
|
function numberArrayToUint8Array(arr) {
|
|
2767
2818
|
return new Uint8Array(arr);
|
|
2768
2819
|
}
|
|
@@ -2779,93 +2830,193 @@ function convertSealedData(sealed) {
|
|
|
2779
2830
|
nonce: numberArrayToUint8Array(sealed.nonce)
|
|
2780
2831
|
};
|
|
2781
2832
|
}
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
method: "POST",
|
|
2792
|
-
headers: {
|
|
2793
|
-
"Content-Type": "application/json"
|
|
2794
|
-
},
|
|
2795
|
-
body: JSON.stringify(body)
|
|
2796
|
-
});
|
|
2797
|
-
} catch (e) {
|
|
2798
|
-
throw new CofheError({
|
|
2799
|
-
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2800
|
-
message: `sealOutput request failed`,
|
|
2801
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2802
|
-
cause: e instanceof Error ? e : void 0,
|
|
2803
|
-
context: {
|
|
2804
|
-
thresholdNetworkUrl,
|
|
2805
|
-
body
|
|
2806
|
-
}
|
|
2807
|
-
});
|
|
2833
|
+
function getSealedDataFromSubmitResponse(value) {
|
|
2834
|
+
if (value.sealed)
|
|
2835
|
+
return value.sealed;
|
|
2836
|
+
if (Array.isArray(value.sealed_data) && Array.isArray(value.ephemeral_public_key) && Array.isArray(value.nonce)) {
|
|
2837
|
+
return {
|
|
2838
|
+
data: value.sealed_data,
|
|
2839
|
+
public_key: value.ephemeral_public_key,
|
|
2840
|
+
nonce: value.nonce
|
|
2841
|
+
};
|
|
2808
2842
|
}
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
errorMessage = response.statusText || errorMessage;
|
|
2816
|
-
}
|
|
2843
|
+
return void 0;
|
|
2844
|
+
}
|
|
2845
|
+
function parseCompletedSealOutputResponse(params) {
|
|
2846
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
2847
|
+
if (value.is_succeed === false) {
|
|
2848
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
2817
2849
|
throw new CofheError({
|
|
2818
2850
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2819
2851
|
message: `sealOutput request failed: ${errorMessage}`,
|
|
2820
|
-
hint: "Check the threshold network URL and request parameters.",
|
|
2821
2852
|
context: {
|
|
2822
2853
|
thresholdNetworkUrl,
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
body
|
|
2854
|
+
requestId,
|
|
2855
|
+
response: value
|
|
2826
2856
|
}
|
|
2827
2857
|
});
|
|
2828
2858
|
}
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
submitResponse = await response.json();
|
|
2832
|
-
} catch (e) {
|
|
2859
|
+
const sealed = "sealed" in value ? value.sealed : getSealedDataFromSubmitResponse(value);
|
|
2860
|
+
if (!sealed) {
|
|
2833
2861
|
throw new CofheError({
|
|
2834
|
-
code: "
|
|
2835
|
-
message: `
|
|
2836
|
-
cause: e instanceof Error ? e : void 0,
|
|
2862
|
+
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2863
|
+
message: `sealOutput request completed but returned no sealed data`,
|
|
2837
2864
|
context: {
|
|
2838
2865
|
thresholdNetworkUrl,
|
|
2839
|
-
|
|
2866
|
+
requestId,
|
|
2867
|
+
response: value
|
|
2840
2868
|
}
|
|
2841
2869
|
});
|
|
2842
2870
|
}
|
|
2843
|
-
|
|
2871
|
+
return convertSealedData(sealed);
|
|
2872
|
+
}
|
|
2873
|
+
async function submitSealOutputRequest(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
2874
|
+
const body = {
|
|
2875
|
+
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
2876
|
+
host_chain_id: chainId,
|
|
2877
|
+
permit: permission
|
|
2878
|
+
};
|
|
2879
|
+
let attemptIndex = 0;
|
|
2880
|
+
for (; ; ) {
|
|
2881
|
+
let response;
|
|
2882
|
+
try {
|
|
2883
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/sealoutput`, {
|
|
2884
|
+
method: "POST",
|
|
2885
|
+
headers: {
|
|
2886
|
+
"Content-Type": "application/json"
|
|
2887
|
+
},
|
|
2888
|
+
body: JSON.stringify(body)
|
|
2889
|
+
});
|
|
2890
|
+
} catch (e) {
|
|
2891
|
+
throw new CofheError({
|
|
2892
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2893
|
+
message: `sealOutput request failed`,
|
|
2894
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
2895
|
+
cause: e instanceof Error ? e : void 0,
|
|
2896
|
+
context: {
|
|
2897
|
+
thresholdNetworkUrl,
|
|
2898
|
+
body,
|
|
2899
|
+
attemptIndex
|
|
2900
|
+
}
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
if (!response.ok) {
|
|
2904
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
2905
|
+
try {
|
|
2906
|
+
const errorBody = await response.json();
|
|
2907
|
+
errorMessage = errorBody.error_message || errorBody.message || errorMessage;
|
|
2908
|
+
} catch {
|
|
2909
|
+
errorMessage = response.statusText || errorMessage;
|
|
2910
|
+
}
|
|
2911
|
+
throw new CofheError({
|
|
2912
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2913
|
+
message: `sealOutput request failed: ${errorMessage}`,
|
|
2914
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
2915
|
+
context: {
|
|
2916
|
+
thresholdNetworkUrl,
|
|
2917
|
+
status: response.status,
|
|
2918
|
+
statusText: response.statusText,
|
|
2919
|
+
body,
|
|
2920
|
+
attemptIndex
|
|
2921
|
+
}
|
|
2922
|
+
});
|
|
2923
|
+
}
|
|
2924
|
+
let submitResponse;
|
|
2925
|
+
if (response.status !== 204) {
|
|
2926
|
+
try {
|
|
2927
|
+
submitResponse = await response.json();
|
|
2928
|
+
} catch (e) {
|
|
2929
|
+
throw new CofheError({
|
|
2930
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2931
|
+
message: `Failed to parse sealOutput submit response`,
|
|
2932
|
+
cause: e instanceof Error ? e : void 0,
|
|
2933
|
+
context: {
|
|
2934
|
+
thresholdNetworkUrl,
|
|
2935
|
+
body,
|
|
2936
|
+
attemptIndex
|
|
2937
|
+
}
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2940
|
+
if (getSealedDataFromSubmitResponse(submitResponse)) {
|
|
2941
|
+
return {
|
|
2942
|
+
kind: "completed",
|
|
2943
|
+
sealed: parseCompletedSealOutputResponse({
|
|
2944
|
+
value: submitResponse,
|
|
2945
|
+
thresholdNetworkUrl,
|
|
2946
|
+
requestId: submitResponse.request_id
|
|
2947
|
+
})
|
|
2948
|
+
};
|
|
2949
|
+
}
|
|
2950
|
+
if (submitResponse.request_id) {
|
|
2951
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
if (response.status === 204) {
|
|
2955
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
2956
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
2957
|
+
throw new CofheError({
|
|
2958
|
+
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2959
|
+
message: `sealOutput submit retried without receiving request_id for ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
2960
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
2961
|
+
context: {
|
|
2962
|
+
thresholdNetworkUrl,
|
|
2963
|
+
body,
|
|
2964
|
+
attemptIndex,
|
|
2965
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS,
|
|
2966
|
+
submitResponse,
|
|
2967
|
+
status: response.status
|
|
2968
|
+
}
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
onPoll?.({
|
|
2972
|
+
operation: "sealoutput",
|
|
2973
|
+
requestId: "",
|
|
2974
|
+
attemptIndex,
|
|
2975
|
+
elapsedMs,
|
|
2976
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS,
|
|
2977
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
2978
|
+
});
|
|
2979
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS));
|
|
2980
|
+
attemptIndex += 1;
|
|
2981
|
+
continue;
|
|
2982
|
+
}
|
|
2844
2983
|
throw new CofheError({
|
|
2845
2984
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2846
2985
|
message: `sealOutput submit response missing request_id`,
|
|
2847
2986
|
context: {
|
|
2848
2987
|
thresholdNetworkUrl,
|
|
2849
2988
|
body,
|
|
2850
|
-
submitResponse
|
|
2989
|
+
submitResponse,
|
|
2990
|
+
attemptIndex
|
|
2851
2991
|
}
|
|
2852
2992
|
});
|
|
2853
2993
|
}
|
|
2854
|
-
return submitResponse.request_id;
|
|
2855
2994
|
}
|
|
2856
|
-
async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2995
|
+
async function pollSealOutputStatus(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
2996
|
+
let attemptIndex = 0;
|
|
2997
|
+
while (true) {
|
|
2998
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
2999
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3000
|
+
minIntervalMs: POLL_INTERVAL_MS,
|
|
3001
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS
|
|
3002
|
+
});
|
|
3003
|
+
onPoll?.({
|
|
3004
|
+
operation: "sealoutput",
|
|
3005
|
+
requestId,
|
|
3006
|
+
attemptIndex,
|
|
3007
|
+
elapsedMs,
|
|
3008
|
+
intervalMs,
|
|
3009
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
3010
|
+
});
|
|
3011
|
+
if (elapsedMs > SEAL_OUTPUT_TIMEOUT_MS) {
|
|
2861
3012
|
throw new CofheError({
|
|
2862
3013
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
2863
|
-
message: `sealOutput polling timed out after ${
|
|
3014
|
+
message: `sealOutput polling timed out after ${SEAL_OUTPUT_TIMEOUT_MS}ms`,
|
|
2864
3015
|
hint: "The request may still be processing. Try again later.",
|
|
2865
3016
|
context: {
|
|
2866
3017
|
thresholdNetworkUrl,
|
|
2867
3018
|
requestId,
|
|
2868
|
-
timeoutMs:
|
|
3019
|
+
timeoutMs: SEAL_OUTPUT_TIMEOUT_MS
|
|
2869
3020
|
}
|
|
2870
3021
|
});
|
|
2871
3022
|
}
|
|
@@ -2934,32 +3085,14 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2934
3085
|
});
|
|
2935
3086
|
}
|
|
2936
3087
|
if (statusResponse.status === "COMPLETED") {
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
context: {
|
|
2943
|
-
thresholdNetworkUrl,
|
|
2944
|
-
requestId,
|
|
2945
|
-
statusResponse
|
|
2946
|
-
}
|
|
2947
|
-
});
|
|
2948
|
-
}
|
|
2949
|
-
if (!statusResponse.sealed) {
|
|
2950
|
-
throw new CofheError({
|
|
2951
|
-
code: "SEAL_OUTPUT_RETURNED_NULL" /* SealOutputReturnedNull */,
|
|
2952
|
-
message: `sealOutput request completed but returned no sealed data`,
|
|
2953
|
-
context: {
|
|
2954
|
-
thresholdNetworkUrl,
|
|
2955
|
-
requestId,
|
|
2956
|
-
statusResponse
|
|
2957
|
-
}
|
|
2958
|
-
});
|
|
2959
|
-
}
|
|
2960
|
-
return convertSealedData(statusResponse.sealed);
|
|
3088
|
+
return parseCompletedSealOutputResponse({
|
|
3089
|
+
value: statusResponse,
|
|
3090
|
+
thresholdNetworkUrl,
|
|
3091
|
+
requestId
|
|
3092
|
+
});
|
|
2961
3093
|
}
|
|
2962
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3094
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3095
|
+
attemptIndex += 1;
|
|
2963
3096
|
}
|
|
2964
3097
|
throw new CofheError({
|
|
2965
3098
|
code: "SEAL_OUTPUT_FAILED" /* SealOutputFailed */,
|
|
@@ -2970,9 +3103,21 @@ async function pollSealOutputStatus(thresholdNetworkUrl, requestId) {
|
|
|
2970
3103
|
}
|
|
2971
3104
|
});
|
|
2972
3105
|
}
|
|
2973
|
-
async function tnSealOutputV2(
|
|
2974
|
-
const
|
|
2975
|
-
|
|
3106
|
+
async function tnSealOutputV2(params) {
|
|
3107
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
3108
|
+
const overallStartTime = Date.now();
|
|
3109
|
+
const submitResult = await submitSealOutputRequest(
|
|
3110
|
+
thresholdNetworkUrl,
|
|
3111
|
+
ctHash,
|
|
3112
|
+
chainId,
|
|
3113
|
+
permission,
|
|
3114
|
+
overallStartTime,
|
|
3115
|
+
onPoll
|
|
3116
|
+
);
|
|
3117
|
+
if (submitResult.kind === "completed") {
|
|
3118
|
+
return submitResult.sealed;
|
|
3119
|
+
}
|
|
3120
|
+
return await pollSealOutputStatus(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
2976
3121
|
}
|
|
2977
3122
|
|
|
2978
3123
|
// core/decrypt/decryptForViewBuilder.ts
|
|
@@ -2981,6 +3126,7 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
2981
3126
|
utype;
|
|
2982
3127
|
permitHash;
|
|
2983
3128
|
permit;
|
|
3129
|
+
pollCallback;
|
|
2984
3130
|
constructor(params) {
|
|
2985
3131
|
super({
|
|
2986
3132
|
config: params.config,
|
|
@@ -3037,6 +3183,10 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3037
3183
|
getAccount() {
|
|
3038
3184
|
return this.account;
|
|
3039
3185
|
}
|
|
3186
|
+
onPoll(callback) {
|
|
3187
|
+
this.pollCallback = callback;
|
|
3188
|
+
return this;
|
|
3189
|
+
}
|
|
3040
3190
|
withPermit(permitOrPermitHash) {
|
|
3041
3191
|
if (typeof permitOrPermitHash === "string") {
|
|
3042
3192
|
this.permitHash = permitOrPermitHash;
|
|
@@ -3160,7 +3310,13 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3160
3310
|
this.assertPublicClient();
|
|
3161
3311
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3162
3312
|
const permission = PermitUtils.getPermission(permit, true);
|
|
3163
|
-
const sealed = await tnSealOutputV2(
|
|
3313
|
+
const sealed = await tnSealOutputV2({
|
|
3314
|
+
ctHash: this.ctHash,
|
|
3315
|
+
chainId: this.chainId,
|
|
3316
|
+
permission,
|
|
3317
|
+
thresholdNetworkUrl,
|
|
3318
|
+
onPoll: this.pollCallback
|
|
3319
|
+
});
|
|
3164
3320
|
return PermitUtils.unseal(permit, sealed);
|
|
3165
3321
|
}
|
|
3166
3322
|
/**
|
|
@@ -3188,7 +3344,6 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3188
3344
|
this.validateUtypeOrThrow();
|
|
3189
3345
|
const permit = await this.getResolvedPermit();
|
|
3190
3346
|
PermitUtils.validate(permit);
|
|
3191
|
-
PermitUtils.isValid(permit);
|
|
3192
3347
|
const chainId = permit._signedDomain.chainId;
|
|
3193
3348
|
let unsealed;
|
|
3194
3349
|
if (chainId === hardhat2.id) {
|
|
@@ -3199,6 +3354,9 @@ var DecryptForViewBuilder = class extends BaseBuilder {
|
|
|
3199
3354
|
return convertViaUtype(this.utype, unsealed);
|
|
3200
3355
|
}
|
|
3201
3356
|
};
|
|
3357
|
+
var UINT_TYPE_MASK = 0x7fn;
|
|
3358
|
+
var TYPE_BYTE_OFFSET = 8n;
|
|
3359
|
+
var getEncryptionTypeFromCtHash = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET & UINT_TYPE_MASK);
|
|
3202
3360
|
async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
3203
3361
|
let allowed;
|
|
3204
3362
|
let error;
|
|
@@ -3236,7 +3394,13 @@ async function cofheMocksDecryptForTx(ctHash, utype, permit, publicClient) {
|
|
|
3236
3394
|
message: `mocks decryptForTx call failed: ACL Access Denied (NotAllowed)`
|
|
3237
3395
|
});
|
|
3238
3396
|
}
|
|
3239
|
-
const
|
|
3397
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
3398
|
+
const normalizedCtHash = BigInt(ctHash);
|
|
3399
|
+
const encryptionType = getEncryptionTypeFromCtHash(normalizedCtHash);
|
|
3400
|
+
const packed = viem.encodePacked(
|
|
3401
|
+
["uint256", "uint32", "uint64", "uint256"],
|
|
3402
|
+
[decryptedValue, encryptionType, BigInt(chainId), normalizedCtHash]
|
|
3403
|
+
);
|
|
3240
3404
|
const messageHash = viem.keccak256(packed);
|
|
3241
3405
|
const signature = await accounts.sign({
|
|
3242
3406
|
hash: messageHash,
|
|
@@ -3308,7 +3472,9 @@ function parseDecryptedBytesToBigInt(decrypted) {
|
|
|
3308
3472
|
|
|
3309
3473
|
// core/decrypt/tnDecryptV2.ts
|
|
3310
3474
|
var POLL_INTERVAL_MS2 = 1e3;
|
|
3311
|
-
var
|
|
3475
|
+
var POLL_MAX_INTERVAL_MS2 = 1e4;
|
|
3476
|
+
var DECRYPT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
3477
|
+
var SUBMIT_RETRY_INTERVAL_MS2 = 1e3;
|
|
3312
3478
|
function assertDecryptSubmitResponseV2(value) {
|
|
3313
3479
|
if (value == null || typeof value !== "object") {
|
|
3314
3480
|
throw new CofheError({
|
|
@@ -3320,16 +3486,65 @@ function assertDecryptSubmitResponseV2(value) {
|
|
|
3320
3486
|
});
|
|
3321
3487
|
}
|
|
3322
3488
|
const v = value;
|
|
3323
|
-
if (
|
|
3489
|
+
if (v.request_id !== null && typeof v.request_id !== "string") {
|
|
3324
3490
|
throw new CofheError({
|
|
3325
3491
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3326
|
-
message: "decrypt submit response
|
|
3492
|
+
message: "decrypt submit response has invalid request_id",
|
|
3327
3493
|
context: {
|
|
3328
3494
|
value
|
|
3329
3495
|
}
|
|
3330
3496
|
});
|
|
3331
3497
|
}
|
|
3332
|
-
return {
|
|
3498
|
+
return {
|
|
3499
|
+
request_id: v.request_id ?? null,
|
|
3500
|
+
status: typeof v.status === "string" ? v.status : void 0,
|
|
3501
|
+
is_succeed: typeof v.is_succeed === "boolean" ? v.is_succeed : void 0,
|
|
3502
|
+
decrypted: Array.isArray(v.decrypted) ? v.decrypted : void 0,
|
|
3503
|
+
signature: typeof v.signature === "string" ? v.signature : void 0,
|
|
3504
|
+
encryption_type: typeof v.encryption_type === "number" ? v.encryption_type : void 0,
|
|
3505
|
+
error_message: typeof v.error_message === "string" || v.error_message === null ? v.error_message : void 0,
|
|
3506
|
+
message: typeof v.message === "string" ? v.message : void 0
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3509
|
+
function parseCompletedDecryptResponseV2(params) {
|
|
3510
|
+
const { value, thresholdNetworkUrl, requestId } = params;
|
|
3511
|
+
if (value.is_succeed === false) {
|
|
3512
|
+
const errorMessage = value.error_message || "Unknown error";
|
|
3513
|
+
throw new CofheError({
|
|
3514
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3515
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3516
|
+
context: {
|
|
3517
|
+
thresholdNetworkUrl,
|
|
3518
|
+
requestId,
|
|
3519
|
+
response: value
|
|
3520
|
+
}
|
|
3521
|
+
});
|
|
3522
|
+
}
|
|
3523
|
+
if (value.error_message) {
|
|
3524
|
+
throw new CofheError({
|
|
3525
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3526
|
+
message: `decrypt request failed: ${value.error_message}`,
|
|
3527
|
+
context: {
|
|
3528
|
+
thresholdNetworkUrl,
|
|
3529
|
+
requestId,
|
|
3530
|
+
response: value
|
|
3531
|
+
}
|
|
3532
|
+
});
|
|
3533
|
+
}
|
|
3534
|
+
if (!Array.isArray(value.decrypted)) {
|
|
3535
|
+
throw new CofheError({
|
|
3536
|
+
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3537
|
+
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3538
|
+
context: {
|
|
3539
|
+
thresholdNetworkUrl,
|
|
3540
|
+
requestId,
|
|
3541
|
+
response: value
|
|
3542
|
+
}
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
const decryptedValue = parseDecryptedBytesToBigInt(value.decrypted);
|
|
3546
|
+
const signature = normalizeTnSignature(value.signature);
|
|
3547
|
+
return { decryptedValue, signature };
|
|
3333
3548
|
}
|
|
3334
3549
|
function assertDecryptStatusResponseV2(value) {
|
|
3335
3550
|
if (value == null || typeof value !== "object") {
|
|
@@ -3375,7 +3590,7 @@ function assertDecryptStatusResponseV2(value) {
|
|
|
3375
3590
|
}
|
|
3376
3591
|
return value;
|
|
3377
3592
|
}
|
|
3378
|
-
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission) {
|
|
3593
|
+
async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, permission, overallStartTime, onPoll) {
|
|
3379
3594
|
const body = {
|
|
3380
3595
|
ct_tempkey: BigInt(ctHash).toString(16).padStart(64, "0"),
|
|
3381
3596
|
host_chain_id: chainId
|
|
@@ -3383,79 +3598,151 @@ async function submitDecryptRequestV2(thresholdNetworkUrl, ctHash, chainId, perm
|
|
|
3383
3598
|
if (permission) {
|
|
3384
3599
|
body.permit = permission;
|
|
3385
3600
|
}
|
|
3386
|
-
let
|
|
3387
|
-
|
|
3388
|
-
response
|
|
3389
|
-
method: "POST",
|
|
3390
|
-
headers: {
|
|
3391
|
-
"Content-Type": "application/json"
|
|
3392
|
-
},
|
|
3393
|
-
body: JSON.stringify(body)
|
|
3394
|
-
});
|
|
3395
|
-
} catch (e) {
|
|
3396
|
-
throw new CofheError({
|
|
3397
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3398
|
-
message: `decrypt request failed`,
|
|
3399
|
-
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3400
|
-
cause: e instanceof Error ? e : void 0,
|
|
3401
|
-
context: {
|
|
3402
|
-
thresholdNetworkUrl,
|
|
3403
|
-
body
|
|
3404
|
-
}
|
|
3405
|
-
});
|
|
3406
|
-
}
|
|
3407
|
-
if (!response.ok) {
|
|
3408
|
-
let errorMessage = `HTTP ${response.status}`;
|
|
3601
|
+
let attemptIndex = 0;
|
|
3602
|
+
for (; ; ) {
|
|
3603
|
+
let response;
|
|
3409
3604
|
try {
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3605
|
+
response = await fetch(`${thresholdNetworkUrl}/v2/decrypt`, {
|
|
3606
|
+
method: "POST",
|
|
3607
|
+
headers: {
|
|
3608
|
+
"Content-Type": "application/json"
|
|
3609
|
+
},
|
|
3610
|
+
body: JSON.stringify(body)
|
|
3611
|
+
});
|
|
3612
|
+
} catch (e) {
|
|
3613
|
+
throw new CofheError({
|
|
3614
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3615
|
+
message: `decrypt request failed`,
|
|
3616
|
+
hint: "Ensure the threshold network URL is valid and reachable.",
|
|
3617
|
+
cause: e instanceof Error ? e : void 0,
|
|
3618
|
+
context: {
|
|
3619
|
+
thresholdNetworkUrl,
|
|
3620
|
+
body,
|
|
3621
|
+
attemptIndex
|
|
3622
|
+
}
|
|
3623
|
+
});
|
|
3416
3624
|
}
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3625
|
+
if (!response.ok) {
|
|
3626
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
3627
|
+
try {
|
|
3628
|
+
const errorBody = await response.json();
|
|
3629
|
+
const maybeMessage = errorBody.error_message || errorBody.message;
|
|
3630
|
+
if (typeof maybeMessage === "string" && maybeMessage.length > 0)
|
|
3631
|
+
errorMessage = maybeMessage;
|
|
3632
|
+
} catch {
|
|
3633
|
+
errorMessage = response.statusText || errorMessage;
|
|
3426
3634
|
}
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3635
|
+
throw new CofheError({
|
|
3636
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3637
|
+
message: `decrypt request failed: ${errorMessage}`,
|
|
3638
|
+
hint: "Check the threshold network URL and request parameters.",
|
|
3639
|
+
context: {
|
|
3640
|
+
thresholdNetworkUrl,
|
|
3641
|
+
status: response.status,
|
|
3642
|
+
statusText: response.statusText,
|
|
3643
|
+
body,
|
|
3644
|
+
attemptIndex
|
|
3645
|
+
}
|
|
3646
|
+
});
|
|
3647
|
+
}
|
|
3648
|
+
let submitResponse;
|
|
3649
|
+
if (response.status !== 204) {
|
|
3650
|
+
let rawJson;
|
|
3651
|
+
try {
|
|
3652
|
+
rawJson = await response.json();
|
|
3653
|
+
} catch (e) {
|
|
3654
|
+
throw new CofheError({
|
|
3655
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3656
|
+
message: `Failed to parse decrypt submit response`,
|
|
3657
|
+
cause: e instanceof Error ? e : void 0,
|
|
3658
|
+
context: {
|
|
3659
|
+
thresholdNetworkUrl,
|
|
3660
|
+
body,
|
|
3661
|
+
attemptIndex
|
|
3662
|
+
}
|
|
3663
|
+
});
|
|
3664
|
+
}
|
|
3665
|
+
submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3666
|
+
if (Array.isArray(submitResponse.decrypted) && typeof submitResponse.signature === "string") {
|
|
3667
|
+
return {
|
|
3668
|
+
kind: "completed",
|
|
3669
|
+
...parseCompletedDecryptResponseV2({
|
|
3670
|
+
value: submitResponse,
|
|
3671
|
+
thresholdNetworkUrl,
|
|
3672
|
+
requestId: submitResponse.request_id
|
|
3673
|
+
})
|
|
3674
|
+
};
|
|
3675
|
+
}
|
|
3676
|
+
if (submitResponse.request_id) {
|
|
3677
|
+
return { kind: "request_id", requestId: submitResponse.request_id };
|
|
3678
|
+
}
|
|
3679
|
+
}
|
|
3680
|
+
if (response.status === 204) {
|
|
3681
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3682
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3683
|
+
throw new CofheError({
|
|
3684
|
+
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3685
|
+
message: `decrypt submit retried without receiving request_id for ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3686
|
+
hint: "The ciphertext may still be propagating. Try again later.",
|
|
3687
|
+
context: {
|
|
3688
|
+
thresholdNetworkUrl,
|
|
3689
|
+
body,
|
|
3690
|
+
attemptIndex,
|
|
3691
|
+
timeoutMs: DECRYPT_TIMEOUT_MS,
|
|
3692
|
+
submitResponse,
|
|
3693
|
+
status: response.status
|
|
3694
|
+
}
|
|
3695
|
+
});
|
|
3696
|
+
}
|
|
3697
|
+
onPoll?.({
|
|
3698
|
+
operation: "decrypt",
|
|
3699
|
+
requestId: "",
|
|
3700
|
+
attemptIndex,
|
|
3701
|
+
elapsedMs,
|
|
3702
|
+
intervalMs: SUBMIT_RETRY_INTERVAL_MS2,
|
|
3703
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3704
|
+
});
|
|
3705
|
+
await new Promise((resolve) => setTimeout(resolve, SUBMIT_RETRY_INTERVAL_MS2));
|
|
3706
|
+
attemptIndex += 1;
|
|
3707
|
+
continue;
|
|
3708
|
+
}
|
|
3433
3709
|
throw new CofheError({
|
|
3434
3710
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3435
|
-
message: `
|
|
3436
|
-
cause: e instanceof Error ? e : void 0,
|
|
3711
|
+
message: `decrypt submit response missing request_id`,
|
|
3437
3712
|
context: {
|
|
3438
3713
|
thresholdNetworkUrl,
|
|
3439
|
-
body
|
|
3714
|
+
body,
|
|
3715
|
+
submitResponse,
|
|
3716
|
+
attemptIndex
|
|
3440
3717
|
}
|
|
3441
3718
|
});
|
|
3442
3719
|
}
|
|
3443
|
-
const submitResponse = assertDecryptSubmitResponseV2(rawJson);
|
|
3444
|
-
return submitResponse.request_id;
|
|
3445
3720
|
}
|
|
3446
|
-
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3721
|
+
async function pollDecryptStatusV2(thresholdNetworkUrl, requestId, overallStartTime, onPoll) {
|
|
3722
|
+
let attemptIndex = 0;
|
|
3723
|
+
while (true) {
|
|
3724
|
+
const elapsedMs = Date.now() - overallStartTime;
|
|
3725
|
+
const intervalMs = computeMinuteRampPollIntervalMs(elapsedMs, {
|
|
3726
|
+
minIntervalMs: POLL_INTERVAL_MS2,
|
|
3727
|
+
maxIntervalMs: POLL_MAX_INTERVAL_MS2
|
|
3728
|
+
});
|
|
3729
|
+
onPoll?.({
|
|
3730
|
+
operation: "decrypt",
|
|
3731
|
+
requestId,
|
|
3732
|
+
attemptIndex,
|
|
3733
|
+
elapsedMs,
|
|
3734
|
+
intervalMs,
|
|
3735
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3736
|
+
});
|
|
3737
|
+
if (elapsedMs > DECRYPT_TIMEOUT_MS) {
|
|
3451
3738
|
throw new CofheError({
|
|
3452
3739
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3453
|
-
message: `decrypt polling timed out after ${
|
|
3740
|
+
message: `decrypt polling timed out after ${DECRYPT_TIMEOUT_MS}ms`,
|
|
3454
3741
|
hint: "The request may still be processing. Try again later.",
|
|
3455
3742
|
context: {
|
|
3456
3743
|
thresholdNetworkUrl,
|
|
3457
3744
|
requestId,
|
|
3458
|
-
timeoutMs:
|
|
3745
|
+
timeoutMs: DECRYPT_TIMEOUT_MS
|
|
3459
3746
|
}
|
|
3460
3747
|
});
|
|
3461
3748
|
}
|
|
@@ -3527,45 +3814,14 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3527
3814
|
}
|
|
3528
3815
|
const statusResponse = assertDecryptStatusResponseV2(rawJson);
|
|
3529
3816
|
if (statusResponse.status === "COMPLETED") {
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
context: {
|
|
3536
|
-
thresholdNetworkUrl,
|
|
3537
|
-
requestId,
|
|
3538
|
-
statusResponse
|
|
3539
|
-
}
|
|
3540
|
-
});
|
|
3541
|
-
}
|
|
3542
|
-
if (statusResponse.error_message) {
|
|
3543
|
-
throw new CofheError({
|
|
3544
|
-
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
3545
|
-
message: `decrypt request failed: ${statusResponse.error_message}`,
|
|
3546
|
-
context: {
|
|
3547
|
-
thresholdNetworkUrl,
|
|
3548
|
-
requestId,
|
|
3549
|
-
statusResponse
|
|
3550
|
-
}
|
|
3551
|
-
});
|
|
3552
|
-
}
|
|
3553
|
-
if (!Array.isArray(statusResponse.decrypted)) {
|
|
3554
|
-
throw new CofheError({
|
|
3555
|
-
code: "DECRYPT_RETURNED_NULL" /* DecryptReturnedNull */,
|
|
3556
|
-
message: "decrypt completed but response missing <decrypted> byte array",
|
|
3557
|
-
context: {
|
|
3558
|
-
thresholdNetworkUrl,
|
|
3559
|
-
requestId,
|
|
3560
|
-
statusResponse
|
|
3561
|
-
}
|
|
3562
|
-
});
|
|
3563
|
-
}
|
|
3564
|
-
const decryptedValue = parseDecryptedBytesToBigInt(statusResponse.decrypted);
|
|
3565
|
-
const signature = normalizeTnSignature(statusResponse.signature);
|
|
3566
|
-
return { decryptedValue, signature };
|
|
3817
|
+
return parseCompletedDecryptResponseV2({
|
|
3818
|
+
value: statusResponse,
|
|
3819
|
+
thresholdNetworkUrl,
|
|
3820
|
+
requestId
|
|
3821
|
+
});
|
|
3567
3822
|
}
|
|
3568
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
3823
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3824
|
+
attemptIndex += 1;
|
|
3569
3825
|
}
|
|
3570
3826
|
throw new CofheError({
|
|
3571
3827
|
code: "DECRYPT_FAILED" /* DecryptFailed */,
|
|
@@ -3576,9 +3832,21 @@ async function pollDecryptStatusV2(thresholdNetworkUrl, requestId) {
|
|
|
3576
3832
|
}
|
|
3577
3833
|
});
|
|
3578
3834
|
}
|
|
3579
|
-
async function tnDecryptV2(
|
|
3580
|
-
const
|
|
3581
|
-
|
|
3835
|
+
async function tnDecryptV2(params) {
|
|
3836
|
+
const { thresholdNetworkUrl, ctHash, chainId, permission, onPoll } = params;
|
|
3837
|
+
const overallStartTime = Date.now();
|
|
3838
|
+
const submitResult = await submitDecryptRequestV2(
|
|
3839
|
+
thresholdNetworkUrl,
|
|
3840
|
+
ctHash,
|
|
3841
|
+
chainId,
|
|
3842
|
+
permission,
|
|
3843
|
+
overallStartTime,
|
|
3844
|
+
onPoll
|
|
3845
|
+
);
|
|
3846
|
+
if (submitResult.kind === "completed") {
|
|
3847
|
+
return submitResult;
|
|
3848
|
+
}
|
|
3849
|
+
return await pollDecryptStatusV2(thresholdNetworkUrl, submitResult.requestId, overallStartTime, onPoll);
|
|
3582
3850
|
}
|
|
3583
3851
|
|
|
3584
3852
|
// core/decrypt/decryptForTxBuilder.ts
|
|
@@ -3587,6 +3855,7 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3587
3855
|
permitHash;
|
|
3588
3856
|
permit;
|
|
3589
3857
|
permitSelection = "unset";
|
|
3858
|
+
pollCallback;
|
|
3590
3859
|
constructor(params) {
|
|
3591
3860
|
super({
|
|
3592
3861
|
config: params.config,
|
|
@@ -3612,6 +3881,10 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3612
3881
|
getAccount() {
|
|
3613
3882
|
return this.account;
|
|
3614
3883
|
}
|
|
3884
|
+
onPoll(callback) {
|
|
3885
|
+
this.pollCallback = callback;
|
|
3886
|
+
return this;
|
|
3887
|
+
}
|
|
3615
3888
|
withPermit(permitOrPermitHash) {
|
|
3616
3889
|
if (this.permitSelection === "with-permit") {
|
|
3617
3890
|
throw new CofheError({
|
|
@@ -3739,7 +4012,13 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3739
4012
|
this.assertPublicClient();
|
|
3740
4013
|
const thresholdNetworkUrl = await this.getThresholdNetworkUrl();
|
|
3741
4014
|
const permission = permit ? PermitUtils.getPermission(permit, true) : null;
|
|
3742
|
-
const { decryptedValue, signature } = await tnDecryptV2(
|
|
4015
|
+
const { decryptedValue, signature } = await tnDecryptV2({
|
|
4016
|
+
ctHash: this.ctHash,
|
|
4017
|
+
chainId: this.chainId,
|
|
4018
|
+
permission,
|
|
4019
|
+
thresholdNetworkUrl,
|
|
4020
|
+
onPoll: this.pollCallback
|
|
4021
|
+
});
|
|
3743
4022
|
return {
|
|
3744
4023
|
ctHash: this.ctHash,
|
|
3745
4024
|
decryptedValue,
|
|
@@ -3757,7 +4036,6 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3757
4036
|
const permit = await this.getResolvedPermit();
|
|
3758
4037
|
if (permit !== null) {
|
|
3759
4038
|
PermitUtils.validate(permit);
|
|
3760
|
-
PermitUtils.isValid(permit);
|
|
3761
4039
|
const chainId = permit._signedDomain.chainId;
|
|
3762
4040
|
if (chainId === hardhat2.id) {
|
|
3763
4041
|
return await this.mocksDecryptForTx(permit);
|
|
@@ -3778,6 +4056,35 @@ var DecryptForTxBuilder = class extends BaseBuilder {
|
|
|
3778
4056
|
}
|
|
3779
4057
|
}
|
|
3780
4058
|
};
|
|
4059
|
+
var decryptResultSignerAbi = viem.parseAbi(["function decryptResultSigner() view returns (address)"]);
|
|
4060
|
+
var UINT_TYPE_MASK2 = 0x7fn;
|
|
4061
|
+
var TYPE_BYTE_OFFSET2 = 8n;
|
|
4062
|
+
var getEncryptionTypeFromCtHash2 = (ctHash) => Number(ctHash >> TYPE_BYTE_OFFSET2 & UINT_TYPE_MASK2);
|
|
4063
|
+
var buildDecryptResultHash = (ctHash, cleartext, chainId) => {
|
|
4064
|
+
const encryptionType = getEncryptionTypeFromCtHash2(ctHash);
|
|
4065
|
+
return viem.keccak256(
|
|
4066
|
+
viem.encodePacked(["uint256", "uint32", "uint64", "uint256"], [cleartext, encryptionType, BigInt(chainId), ctHash])
|
|
4067
|
+
);
|
|
4068
|
+
};
|
|
4069
|
+
async function verifyDecryptResult(handle, cleartext, signature, publicClient) {
|
|
4070
|
+
const chainId = publicClient.chain?.id ?? await publicClient.getChainId();
|
|
4071
|
+
const expectedSigner = await publicClient.readContract({
|
|
4072
|
+
address: TASK_MANAGER_ADDRESS,
|
|
4073
|
+
abi: decryptResultSignerAbi,
|
|
4074
|
+
functionName: "decryptResultSigner",
|
|
4075
|
+
args: []
|
|
4076
|
+
});
|
|
4077
|
+
if (viem.isAddressEqual(expectedSigner, viem.zeroAddress))
|
|
4078
|
+
return true;
|
|
4079
|
+
const ctHash = BigInt(handle);
|
|
4080
|
+
const messageHash = buildDecryptResultHash(ctHash, cleartext, chainId);
|
|
4081
|
+
try {
|
|
4082
|
+
const recovered = await viem.recoverAddress({ hash: messageHash, signature });
|
|
4083
|
+
return viem.isAddressEqual(recovered, expectedSigner);
|
|
4084
|
+
} catch {
|
|
4085
|
+
return false;
|
|
4086
|
+
}
|
|
4087
|
+
}
|
|
3781
4088
|
|
|
3782
4089
|
// core/client.ts
|
|
3783
4090
|
var InitialConnectStore = {
|
|
@@ -3896,6 +4203,11 @@ function createCofheClientBase(opts) {
|
|
|
3896
4203
|
requireConnected: _requireConnected
|
|
3897
4204
|
});
|
|
3898
4205
|
}
|
|
4206
|
+
function verifyDecryptResult2(handle, cleartext, signature) {
|
|
4207
|
+
_requireConnected();
|
|
4208
|
+
const { publicClient } = connectStore.getState();
|
|
4209
|
+
return verifyDecryptResult(handle, cleartext, signature, publicClient);
|
|
4210
|
+
}
|
|
3899
4211
|
const _getChainIdAndAccount = (chainId, account) => {
|
|
3900
4212
|
const state = connectStore.getState();
|
|
3901
4213
|
const _chainId = chainId ?? state.chainId;
|
|
@@ -3978,6 +4290,7 @@ function createCofheClientBase(opts) {
|
|
|
3978
4290
|
},
|
|
3979
4291
|
// Utils (no context needed)
|
|
3980
4292
|
getHash: permits.getHash,
|
|
4293
|
+
export: permits.export,
|
|
3981
4294
|
serialize: permits.serialize,
|
|
3982
4295
|
deserialize: permits.deserialize
|
|
3983
4296
|
};
|
|
@@ -4006,6 +4319,7 @@ function createCofheClientBase(opts) {
|
|
|
4006
4319
|
*/
|
|
4007
4320
|
decryptHandle: decryptForView,
|
|
4008
4321
|
decryptForTx,
|
|
4322
|
+
verifyDecryptResult: verifyDecryptResult2,
|
|
4009
4323
|
permits: clientPermits
|
|
4010
4324
|
// Add SDK-specific methods below that require connection
|
|
4011
4325
|
// Example:
|
|
@@ -4069,16 +4383,22 @@ var fromHexString2 = (hexString) => {
|
|
|
4069
4383
|
return new Uint8Array();
|
|
4070
4384
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
4071
4385
|
};
|
|
4386
|
+
var _deserializeTfhePublicKey = (buff) => {
|
|
4387
|
+
return nodeTfhe.TfheCompactPublicKey.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
4388
|
+
};
|
|
4389
|
+
var _deserializeCompactPkeCrs = (buff) => {
|
|
4390
|
+
return nodeTfhe.CompactPkeCrs.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
4391
|
+
};
|
|
4072
4392
|
var tfhePublicKeyDeserializer = (buff) => {
|
|
4073
|
-
|
|
4393
|
+
_deserializeTfhePublicKey(buff);
|
|
4074
4394
|
};
|
|
4075
4395
|
var compactPkeCrsDeserializer = (buff) => {
|
|
4076
|
-
|
|
4396
|
+
_deserializeCompactPkeCrs(buff);
|
|
4077
4397
|
};
|
|
4078
4398
|
var zkBuilderAndCrsGenerator = (fhe, crs) => {
|
|
4079
|
-
const fhePublicKey =
|
|
4399
|
+
const fhePublicKey = _deserializeTfhePublicKey(fhe);
|
|
4080
4400
|
const zkBuilder = nodeTfhe.ProvenCompactCiphertextList.builder(fhePublicKey);
|
|
4081
|
-
const zkCrs =
|
|
4401
|
+
const zkCrs = _deserializeCompactPkeCrs(crs);
|
|
4082
4402
|
return { zkBuilder, zkCrs };
|
|
4083
4403
|
};
|
|
4084
4404
|
function createCofheConfig(config) {
|