@zama-fhe/relayer-sdk 0.4.0-alpha.1 → 0.4.0-alpha.2

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/lib/web.js CHANGED
@@ -16255,7 +16255,7 @@ const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
16255
16255
  const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
16256
16256
 
16257
16257
  // This file is auto-generated
16258
- const version = '0.4.0-alpha.1';
16258
+ const version = '0.4.0-alpha.2';
16259
16259
  const sdkName = '@zama-fhe/relayer-sdk';
16260
16260
 
16261
16261
  function getErrorCause(e) {
@@ -17057,9 +17057,9 @@ function assertRecordStringArrayProperty(o, property, objName) {
17057
17057
  }
17058
17058
  }
17059
17059
  }
17060
- function safeJSONstringify(o) {
17060
+ function safeJSONstringify(o, space) {
17061
17061
  try {
17062
- return JSON.stringify(o, (_, v) => typeof v === 'bigint' ? v.toString() : v);
17062
+ return JSON.stringify(o, (_, v) => (typeof v === 'bigint' ? v.toString() : v), space);
17063
17063
  }
17064
17064
  catch {
17065
17065
  return '';
@@ -17175,6 +17175,17 @@ const NumEncryptedBits = {
17175
17175
  7: 160, // eaddress
17176
17176
  8: 256, // euint256
17177
17177
  };
17178
+ // export function getHandleType(handle: `0x${string}`): number {
17179
+ // if (handle.length !== 66) {
17180
+ // throw new Error(`Handle ${handle} is not of valid length`);
17181
+ // }
17182
+ // const hexPair = handle.slice(-4, -2).toLowerCase();
17183
+ // const typeDiscriminant = parseInt(hexPair, 16);
17184
+ // if (!(typeDiscriminant in NumEncryptedBits)) {
17185
+ // throw new Error(`Handle ${handle} is not of valid type`);
17186
+ // }
17187
+ // return typeDiscriminant;
17188
+ // }
17178
17189
  function checkEncryptedBits(handles) {
17179
17190
  let total = 0;
17180
17191
  for (const handle of handles) {
@@ -17232,7 +17243,7 @@ function isBytes(value, bytewidth) {
17232
17243
  if (!(value instanceof Uint8Array)) {
17233
17244
  return false;
17234
17245
  }
17235
- return value.length === bytewidth ;
17246
+ return bytewidth ? value.length === bytewidth : true;
17236
17247
  }
17237
17248
  function isBytesHex(value, bytewidth) {
17238
17249
  if (!is0x(value)) {
@@ -17465,6 +17476,54 @@ function assertUint8ArrayProperty(o, property, objName) {
17465
17476
  });
17466
17477
  }
17467
17478
  }
17479
+ ////////////////////////////////////////////////////////////////////////////////
17480
+ // Hex
17481
+ ////////////////////////////////////////////////////////////////////////////////
17482
+ const HEX_CHARS = {
17483
+ '0': 0,
17484
+ '1': 1,
17485
+ '2': 2,
17486
+ '3': 3,
17487
+ '4': 4,
17488
+ '5': 5,
17489
+ '6': 6,
17490
+ '7': 7,
17491
+ '8': 8,
17492
+ '9': 9,
17493
+ a: 10,
17494
+ b: 11,
17495
+ c: 12,
17496
+ d: 13,
17497
+ e: 14,
17498
+ f: 15,
17499
+ A: 10,
17500
+ B: 11,
17501
+ C: 12,
17502
+ D: 13,
17503
+ E: 14,
17504
+ F: 15,
17505
+ };
17506
+ Object.freeze(HEX_CHARS);
17507
+ const HEX_BYTES = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
17508
+ Object.freeze(HEX_BYTES);
17509
+ const HEX_CHARS_CODES = new Uint8Array([
17510
+ 48,
17511
+ 49,
17512
+ 50,
17513
+ 51,
17514
+ 52,
17515
+ 53,
17516
+ 54,
17517
+ 55,
17518
+ 56,
17519
+ 57, // '0'-'9'
17520
+ 97,
17521
+ 98,
17522
+ 99,
17523
+ 100,
17524
+ 101,
17525
+ 102, // 'a'-'f'
17526
+ ]);
17468
17527
  /**
17469
17528
  * Convert a Uint8Array to a hex string (without 0x prefix).
17470
17529
  */
@@ -17484,15 +17543,49 @@ function bytesToHexNo0x(bytes) {
17484
17543
  function bytesToHex(bytes) {
17485
17544
  return `0x${bytesToHexNo0x(bytes)}`;
17486
17545
  }
17546
+ function bytesToHexLarge(bytes) {
17547
+ const out = new Uint8Array(2 + bytes.length * 2);
17548
+ out[0] = 48; // '0'
17549
+ out[1] = 120; // 'x'
17550
+ for (let i = 0; i < bytes.length; i++) {
17551
+ const j = 2 + i * 2;
17552
+ out[j] = HEX_CHARS_CODES[bytes[i] >> 4];
17553
+ out[j + 1] = HEX_CHARS_CODES[bytes[i] & 0xf];
17554
+ }
17555
+ return new TextDecoder().decode(out);
17556
+ }
17487
17557
  /**
17488
17558
  * Convert a hex string prefixed by 0x or not to a Uint8Array
17559
+ * Any invalid byte string is converted to 0
17560
+ * "0xzzff" = [0, 255]
17561
+ * "0xzfff" = [0, 255]
17489
17562
  */
17490
17563
  function hexToBytes(hexString) {
17564
+ if (hexString.length % 2 !== 0) {
17565
+ throw new Error('Invalid hex string: odd length');
17566
+ }
17491
17567
  const arr = hexString.replace(/^(0x)/, '').match(/.{1,2}/g);
17492
17568
  if (!arr)
17493
17569
  return new Uint8Array();
17494
17570
  return Uint8Array.from(arr.map((byte) => parseInt(byte, 16)));
17495
17571
  }
17572
+ function hexToBytesFaster(hexString, strict = false) {
17573
+ const offset = hexString[0] === '0' && hexString[1] === 'x' ? 2 : 0;
17574
+ const len = hexString.length - offset;
17575
+ if (len % 2 !== 0) {
17576
+ throw new Error('Invalid hex string: odd length');
17577
+ }
17578
+ const bytes = new Uint8Array(len / 2);
17579
+ for (let i = 0; i < bytes.length; i++) {
17580
+ const hi = HEX_CHARS[hexString[offset + i * 2]];
17581
+ const lo = HEX_CHARS[hexString[offset + i * 2 + 1]];
17582
+ if ((hi === undefined || lo === undefined) && strict) {
17583
+ throw new Error(`Invalid hex character at position ${offset + i * 2}`);
17584
+ }
17585
+ bytes[i] = (hi << 4) | lo;
17586
+ }
17587
+ return bytes;
17588
+ }
17496
17589
  /**
17497
17590
  * Convert a Uint8Array to a bigint
17498
17591
  */
@@ -17506,9 +17599,6 @@ function bytesToBigInt(byteArray) {
17506
17599
  }
17507
17600
  return result;
17508
17601
  }
17509
- function toHexString(bytes, with0x = false) {
17510
- return `${with0x ? '0x' : ''}${bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')}`;
17511
- }
17512
17602
  async function fetchBytes(url) {
17513
17603
  const response = await fetch(url);
17514
17604
  if (!response.ok) {
@@ -17600,8 +17690,8 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
17600
17690
  const publicKeySanitized = publicKey.replace(/^(0x)/, '');
17601
17691
  const handleContractPairs = _handles.map((h) => ({
17602
17692
  handle: typeof h.handle === 'string'
17603
- ? toHexString(hexToBytes(h.handle), true)
17604
- : toHexString(h.handle, true),
17693
+ ? bytesToHex(hexToBytes(h.handle))
17694
+ : bytesToHex(h.handle),
17605
17695
  contractAddress: getAddress$1(h.contractAddress),
17606
17696
  }));
17607
17697
  checkEncryptedBits(handleContractPairs.map((h) => h.handle));
@@ -17817,9 +17907,8 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
17817
17907
 
17818
17908
  const MAX_UINT64 = BigInt('18446744073709551615'); // 2^64 - 1
17819
17909
  BigInt('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
17820
- const MAX_UINT32 = 0xffffffff;
17821
17910
  const MAX_UINT8 = 0xff;
17822
- function numberToHex(num) {
17911
+ function numberToHexNo0x(num) {
17823
17912
  let hex = num.toString(16);
17824
17913
  return hex.length % 2 ? '0' + hex : hex;
17825
17914
  }
@@ -17853,25 +17942,19 @@ function isUint8(value) {
17853
17942
  }
17854
17943
  return value <= MAX_UINT8;
17855
17944
  }
17856
- function isUint32(value) {
17857
- if (!isUint(value)) {
17858
- return false;
17859
- }
17860
- return value <= MAX_UINT32;
17861
- }
17862
17945
  function isUint64(value) {
17863
17946
  if (!isUint(value)) {
17864
17947
  return false;
17865
17948
  }
17866
17949
  return value <= MAX_UINT64;
17867
17950
  }
17868
- function uint32ToBytes32(uint32) {
17869
- if (!isUint32(uint32)) {
17870
- throw new InvalidTypeError({ expectedType: 'Uint32' });
17951
+ function numberToBytes32(num) {
17952
+ if (!isUintNumber(num)) {
17953
+ throw new InvalidTypeError({ expectedType: 'Uint' });
17871
17954
  }
17872
17955
  const buffer = new ArrayBuffer(32);
17873
17956
  const view = new DataView(buffer);
17874
- view.setUint32(28, Number(uint32), false);
17957
+ view.setBigUint64(24, BigInt(num), false);
17875
17958
  return new Uint8Array(buffer);
17876
17959
  }
17877
17960
  function assertIsUint8(value) {
@@ -17969,63 +18052,213 @@ function checksummedAddressToBytes20(address) {
17969
18052
  class FhevmHandleError extends RelayerErrorBase {
17970
18053
  constructor({ handle, message }) {
17971
18054
  super({
17972
- message: message ?? `FHEVM Handle "${handle}" is invalid.`,
18055
+ message: message ??
18056
+ (handle
18057
+ ? `FHEVM Handle "${handle}" is invalid.`
18058
+ : `FHEVM Handle is invalid.`),
17973
18059
  name: 'FhevmHandleError',
17974
18060
  });
17975
18061
  }
17976
18062
  }
17977
18063
 
18064
+ class FheTypeError extends RelayerErrorBase {
18065
+ constructor({ fheTypeId, message, }) {
18066
+ super({
18067
+ message: message ??
18068
+ (fheTypeId
18069
+ ? `FheTypeId "${fheTypeId}" is invalid.`
18070
+ : `FheTypeId is invalid.`),
18071
+ name: 'FheTypeError',
18072
+ });
18073
+ }
18074
+ }
18075
+
18076
+ const FheTypeIdToName = {
18077
+ 0: 'ebool',
18078
+ //1: 'euint4', has been deprecated
18079
+ 2: 'euint8',
18080
+ 3: 'euint16',
18081
+ 4: 'euint32',
18082
+ 5: 'euint64',
18083
+ 6: 'euint128',
18084
+ 7: 'eaddress',
18085
+ 8: 'euint256',
18086
+ };
18087
+ const FheTypeIdToEncryptionBitwidth = {
18088
+ 0: 2,
18089
+ //1:?, euint4 has been deprecated
18090
+ 2: 8,
18091
+ 3: 16,
18092
+ 4: 32,
18093
+ 5: 64,
18094
+ 6: 128,
18095
+ 7: 160,
18096
+ 8: 256,
18097
+ };
18098
+ const EncryptionBitwidthToFheTypeId = {
18099
+ 2: 0,
18100
+ //?:1, euint4 has been deprecated
18101
+ 8: 2,
18102
+ 16: 3,
18103
+ 32: 4,
18104
+ 64: 5,
18105
+ 128: 6,
18106
+ 160: 7,
18107
+ 256: 8,
18108
+ };
18109
+ const FheTypeIdToSolidityPrimitiveTypeName = {
18110
+ 0: 'bool',
18111
+ //1:'uint256', euint4 has been deprecated
18112
+ 2: 'uint256',
18113
+ 3: 'uint256',
18114
+ 4: 'uint256',
18115
+ 5: 'uint256',
18116
+ 6: 'uint256',
18117
+ 7: 'address',
18118
+ 8: 'uint256',
18119
+ };
18120
+ Object.freeze(FheTypeIdToEncryptionBitwidth);
18121
+ Object.freeze(EncryptionBitwidthToFheTypeId);
18122
+ Object.freeze(FheTypeIdToSolidityPrimitiveTypeName);
18123
+ ////////////////////////////////////////////////////////////////////////////////
18124
+ // Type Guards
18125
+ ////////////////////////////////////////////////////////////////////////////////
18126
+ /**
18127
+ * Checks if a value is a valid FheTypeId.
18128
+ * @example isFheTypeId(2) // true (euint8)
18129
+ * @example isFheTypeId(1) // false (euint4 is deprecated)
18130
+ */
18131
+ function isFheTypeId(value) {
18132
+ switch (value) {
18133
+ case 0:
18134
+ // 1: euint4 is deprecated
18135
+ case 2:
18136
+ case 3:
18137
+ case 4:
18138
+ case 5:
18139
+ case 6:
18140
+ case 7:
18141
+ case 8:
18142
+ return true;
18143
+ default:
18144
+ return false;
18145
+ }
18146
+ }
18147
+ /**
18148
+ * Checks if a value is a valid encryption bit width.
18149
+ * @example isEncryptionBits(8) // true
18150
+ * @example isEncryptionBits(4) // false (euint4 is deprecated)
18151
+ */
18152
+ function isEncryptionBits(value) {
18153
+ if (typeof value !== 'number') {
18154
+ return false;
18155
+ }
18156
+ return value in EncryptionBitwidthToFheTypeId;
18157
+ }
18158
+ ////////////////////////////////////////////////////////////////////////////////
18159
+ // FheTypeId extractors
18160
+ ////////////////////////////////////////////////////////////////////////////////
18161
+ /**
18162
+ * Converts an encryption bit width to its corresponding FheTypeId.
18163
+ * @throws {FheTypeError} If bitwidth is not a valid encryption bit width.
18164
+ * @example fheTypeIdFromEncryptionBits(8) // 2 (euint8)
18165
+ */
18166
+ function fheTypeIdFromEncryptionBits(bitwidth) {
18167
+ if (!isEncryptionBits(bitwidth)) {
18168
+ throw new FheTypeError({
18169
+ message: `Invalid encryption bits ${bitwidth}`,
18170
+ });
18171
+ }
18172
+ return EncryptionBitwidthToFheTypeId[bitwidth];
18173
+ }
18174
+ /**
18175
+ * Converts an FheTypeId to its corresponding FheTypeName.
18176
+ * @throws {FheTypeError} If id is not a valid FheTypeId.
18177
+ * @example fheTypeNameFromId(2) // 'euint8'
18178
+ */
18179
+ function fheTypeNameFromId(id) {
18180
+ if (!isFheTypeId(id)) {
18181
+ throw new FheTypeError({
18182
+ message: `Invalid FheType id '${id}'`,
18183
+ });
18184
+ }
18185
+ return FheTypeIdToName[id];
18186
+ }
18187
+ ////////////////////////////////////////////////////////////////////////////////
18188
+ // Solidity primitive type names
18189
+ ////////////////////////////////////////////////////////////////////////////////
18190
+ /**
18191
+ * Returns the Solidity primitive type name for an FheTypeId.
18192
+ * @example solidityPrimitiveTypeNameFromFheTypeId(0) // 'bool'
18193
+ * @example solidityPrimitiveTypeNameFromFheTypeId(7) // 'address'
18194
+ * @example solidityPrimitiveTypeNameFromFheTypeId(2) // 'uint256'
18195
+ */
18196
+ function solidityPrimitiveTypeNameFromFheTypeId(typeId) {
18197
+ if (!isFheTypeId(typeId)) {
18198
+ throw new FheTypeError({
18199
+ message: `Invalid FheType id '${typeId}'`,
18200
+ });
18201
+ }
18202
+ return FheTypeIdToSolidityPrimitiveTypeName[typeId];
18203
+ }
18204
+ ////////////////////////////////////////////////////////////////////////////////
18205
+ // Encryption Bits
18206
+ ////////////////////////////////////////////////////////////////////////////////
18207
+ /**
18208
+ * Returns the encryption bit width for an FheTypeId.
18209
+ * @example encryptionBitsFromFheTypeId(2) // 8 (euint8)
18210
+ * @example encryptionBitsFromFheTypeId(7) // 160 (eaddress)
18211
+ */
18212
+ function encryptionBitsFromFheTypeId(typeId) {
18213
+ if (!isFheTypeId(typeId)) {
18214
+ throw new FheTypeError({
18215
+ message: `Invalid FheType id '${typeId}'`,
18216
+ });
18217
+ }
18218
+ return FheTypeIdToEncryptionBitwidth[typeId];
18219
+ }
18220
+
17978
18221
  ////////////////////////////////////////////////////////////////////////////////
17979
18222
  // FhevmHandle
17980
18223
  ////////////////////////////////////////////////////////////////////////////////
17981
18224
  class FhevmHandle {
18225
+ //////////////////////////////////////////////////////////////////////////////
18226
+ // Instance Properties
18227
+ //////////////////////////////////////////////////////////////////////////////
17982
18228
  _hash21;
17983
18229
  _chainId;
17984
18230
  _fheTypeId;
17985
18231
  _version;
17986
18232
  _computed;
17987
18233
  _index;
18234
+ _handleBytes32Hex;
18235
+ _handleBytes32;
18236
+ //////////////////////////////////////////////////////////////////////////////
18237
+ // Static Constants
18238
+ //////////////////////////////////////////////////////////////////////////////
17988
18239
  static RAW_CT_HASH_DOMAIN_SEPARATOR = 'ZK-w_rct';
17989
18240
  static HANDLE_HASH_DOMAIN_SEPARATOR = 'ZK-w_hdl';
17990
- static FheTypeIdToEncryptionBitwidths = {
17991
- 0: 2,
17992
- 2: 8,
17993
- 3: 16,
17994
- 4: 32,
17995
- 5: 64,
17996
- 6: 128,
17997
- 7: 160,
17998
- 8: 256,
17999
- };
18000
- static FheTypeEncryptionBitwidthsToId = {
18001
- 2: 0,
18002
- 8: 2,
18003
- 16: 3,
18004
- 32: 4,
18005
- 64: 5,
18006
- 128: 6,
18007
- 160: 7,
18008
- 256: 8,
18009
- };
18010
- static FheTypeIdToSolidityPrimitiveType = {
18011
- 0: 'bool',
18012
- 2: 'uint256',
18013
- 3: 'uint256',
18014
- 4: 'uint256',
18015
- 5: 'uint256',
18016
- 6: 'uint256',
18017
- 7: 'address',
18018
- 8: 'uint256',
18019
- };
18020
- static {
18021
- Object.freeze(FhevmHandle.FheTypeIdToEncryptionBitwidths);
18022
- Object.freeze(FhevmHandle.FheTypeEncryptionBitwidthsToId);
18023
- }
18024
- constructor(hash21, chainId, fheTypeId, version, computed, index) {
18241
+ static CURRENT_CIPHERTEXT_VERSION = 0;
18242
+ //////////////////////////////////////////////////////////////////////////////
18243
+ // Constructor
18244
+ //////////////////////////////////////////////////////////////////////////////
18245
+ constructor({ hash21, chainId, fheTypeId, version, computed, index, handleBytes32, handleBytes32Hex, }) {
18246
+ if (!isUintNumber(chainId)) {
18247
+ throw new FhevmHandleError({
18248
+ message: 'ChainId must be a positive integer',
18249
+ });
18250
+ }
18025
18251
  if (BigInt(chainId) > MAX_UINT64) {
18026
18252
  // fhevm assumes chainID is only taking up to 8 bytes
18027
- throw new Error('ChainId exceeds maximum allowed value (8 bytes)');
18253
+ throw new FhevmHandleError({
18254
+ message: 'ChainId exceeds maximum allowed value (8 bytes)',
18255
+ });
18256
+ }
18257
+ if (!isBytesHex(hash21, 21)) {
18258
+ throw new FhevmHandleError({ message: 'Hash21 should be 21 bytes long' });
18028
18259
  }
18260
+ this._handleBytes32 = handleBytes32;
18261
+ this._handleBytes32Hex = handleBytes32Hex;
18029
18262
  this._hash21 = hash21;
18030
18263
  this._chainId = chainId;
18031
18264
  this._fheTypeId = fheTypeId;
@@ -18035,6 +18268,9 @@ class FhevmHandle {
18035
18268
  this._index = index;
18036
18269
  }
18037
18270
  }
18271
+ //////////////////////////////////////////////////////////////////////////////
18272
+ // Instance Getters
18273
+ //////////////////////////////////////////////////////////////////////////////
18038
18274
  get hash21() {
18039
18275
  return this._hash21;
18040
18276
  }
@@ -18044,6 +18280,9 @@ class FhevmHandle {
18044
18280
  get fheTypeId() {
18045
18281
  return this._fheTypeId;
18046
18282
  }
18283
+ get fheTypeName() {
18284
+ return fheTypeNameFromId(this._fheTypeId);
18285
+ }
18047
18286
  get version() {
18048
18287
  return this._version;
18049
18288
  }
@@ -18053,6 +18292,106 @@ class FhevmHandle {
18053
18292
  get index() {
18054
18293
  return this._index;
18055
18294
  }
18295
+ get encryptedBitwidth() {
18296
+ return encryptionBitsFromFheTypeId(this._fheTypeId);
18297
+ }
18298
+ get solidityPrimitiveTypeName() {
18299
+ return solidityPrimitiveTypeNameFromFheTypeId(this._fheTypeId);
18300
+ }
18301
+ toJSON() {
18302
+ return {
18303
+ handle: this.toBytes32Hex(),
18304
+ fheTypeName: this.fheTypeName,
18305
+ fheTypeId: this.fheTypeId,
18306
+ chainId: this.chainId,
18307
+ index: this.index,
18308
+ computed: this.computed,
18309
+ encryptedBitwidth: this.encryptedBitwidth,
18310
+ version: this.version,
18311
+ solidityPrimitiveTypeName: this.solidityPrimitiveTypeName,
18312
+ hash21: this.hash21,
18313
+ };
18314
+ }
18315
+ //////////////////////////////////////////////////////////////////////////////
18316
+ // Instance Serialization
18317
+ //////////////////////////////////////////////////////////////////////////////
18318
+ toBytes32() {
18319
+ if (this._handleBytes32 === undefined) {
18320
+ assertRelayer((this._index === undefined && this._computed) ||
18321
+ (this._index !== undefined && this._index < 255 && !this._computed));
18322
+ const chainId32Bytes = numberToBytes32(this._chainId);
18323
+ const chainId8Bytes = chainId32Bytes.subarray(24, 32);
18324
+ const handleHash21 = hexToBytes(this._hash21);
18325
+ assertRelayer(handleHash21.length === 21);
18326
+ const handleBytes32AsBytes = new Uint8Array(32);
18327
+ handleBytes32AsBytes.set(handleHash21, 0);
18328
+ handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
18329
+ handleBytes32AsBytes.set(chainId8Bytes, 22);
18330
+ handleBytes32AsBytes[30] = this._fheTypeId;
18331
+ handleBytes32AsBytes[31] = this._version;
18332
+ this._handleBytes32 = handleBytes32AsBytes;
18333
+ }
18334
+ return this._handleBytes32;
18335
+ }
18336
+ toBytes32Hex() {
18337
+ if (this._handleBytes32Hex === undefined) {
18338
+ this._handleBytes32Hex = bytesToHex(this.toBytes32());
18339
+ }
18340
+ return this._handleBytes32Hex;
18341
+ }
18342
+ //////////////////////////////////////////////////////////////////////////////
18343
+ // Static Factory Methods
18344
+ //////////////////////////////////////////////////////////////////////////////
18345
+ static fromComponents(params) {
18346
+ return new FhevmHandle(params);
18347
+ }
18348
+ static fromBytes32(handle) {
18349
+ if (!isBytes32(handle)) {
18350
+ throw new FhevmHandleError({
18351
+ message: `FHEVM Handle is not a valid bytes32 array.`,
18352
+ });
18353
+ }
18354
+ const bytes = handle;
18355
+ // Extract hash21 (bytes 0-20)
18356
+ const hash21 = bytesToHex(bytes.slice(0, 21));
18357
+ // Extract index (byte 21) - 255 means computed
18358
+ const indexByte = bytes[21];
18359
+ const computed = indexByte === 255;
18360
+ const index = computed ? undefined : indexByte;
18361
+ // Extract chainId (bytes 22-29, 8 bytes as big-endian uint64)
18362
+ let chainId = 0;
18363
+ for (let i = 22; i < 30; i++) {
18364
+ chainId = chainId * 256 + bytes[i];
18365
+ }
18366
+ // Extract fheTypeId (byte 30)
18367
+ const fheTypeIdByte = bytes[30];
18368
+ if (!isFheTypeId(fheTypeIdByte)) {
18369
+ throw new FhevmHandleError({
18370
+ handle,
18371
+ message: `FHEVM Handle "${handle}" is invalid. Unknown FheType: ${fheTypeIdByte}`,
18372
+ });
18373
+ }
18374
+ // Extract version (byte 31)
18375
+ const version = bytes[31];
18376
+ return new FhevmHandle({
18377
+ hash21,
18378
+ chainId,
18379
+ fheTypeId: fheTypeIdByte,
18380
+ version,
18381
+ computed,
18382
+ index,
18383
+ handleBytes32: handle,
18384
+ });
18385
+ }
18386
+ static fromBytes32Hex(handle) {
18387
+ if (!isBytes32Hex(handle)) {
18388
+ throw new FhevmHandleError({ handle });
18389
+ }
18390
+ const bytes = hexToBytes(handle);
18391
+ const h = FhevmHandle.fromBytes32(bytes);
18392
+ h._handleBytes32Hex = handle;
18393
+ return h;
18394
+ }
18056
18395
  static fromZKProof(params) {
18057
18396
  assertIsChecksummedAddress(params.aclAddress);
18058
18397
  assertIsUint64(params.chainId);
@@ -18062,7 +18401,7 @@ class FhevmHandle {
18062
18401
  fheTypeIds = params.fheTypeIds;
18063
18402
  }
18064
18403
  else if (params.fheTypeEncryptionBitwidths !== undefined) {
18065
- fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => FhevmHandle.FheTypeEncryptionBitwidthsToId[w]);
18404
+ fheTypeIds = params.fheTypeEncryptionBitwidths.map((w) => fheTypeIdFromEncryptionBits(w));
18066
18405
  }
18067
18406
  else {
18068
18407
  throw new InternalError({
@@ -18093,22 +18432,69 @@ class FhevmHandle {
18093
18432
  const handles = [];
18094
18433
  for (let i = 0; i < fheTypeIds.length; ++i) {
18095
18434
  const hash21 = FhevmHandle._computeInputHash21(hexToBytes(blobHashBytes32Hex), params.aclAddress, params.chainId, i);
18096
- handles.push(new FhevmHandle(hash21, params.chainId, fheTypeIds[i], params.ciphertextVersion, false, i));
18435
+ handles.push(new FhevmHandle({
18436
+ hash21,
18437
+ chainId: params.chainId,
18438
+ fheTypeId: fheTypeIds[i],
18439
+ version: params.ciphertextVersion,
18440
+ computed: false,
18441
+ index: i,
18442
+ }));
18097
18443
  }
18098
18444
  return handles;
18099
18445
  }
18446
+ //////////////////////////////////////////////////////////////////////////////
18447
+ // Static Parsing
18448
+ //////////////////////////////////////////////////////////////////////////////
18449
+ static parse(handle) {
18450
+ if (isBytes(handle)) {
18451
+ return FhevmHandle.fromBytes32(handle);
18452
+ }
18453
+ return FhevmHandle.fromBytes32Hex(handle);
18454
+ }
18455
+ static canParse(handle) {
18456
+ try {
18457
+ FhevmHandle.parse(handle);
18458
+ return true;
18459
+ }
18460
+ catch {
18461
+ return false;
18462
+ }
18463
+ }
18464
+ //////////////////////////////////////////////////////////////////////////////
18465
+ // Static Assertions
18466
+ //////////////////////////////////////////////////////////////////////////////
18467
+ static assertIsHandleHex(handle) {
18468
+ if (typeof handle !== 'string') {
18469
+ throw new FhevmHandleError({
18470
+ message: 'Invalid bytes32 hexadecimal string',
18471
+ });
18472
+ }
18473
+ if (!FhevmHandle.canParse(handle)) {
18474
+ throw new FhevmHandleError({ handle });
18475
+ }
18476
+ }
18477
+ //////////////////////////////////////////////////////////////////////////////
18478
+ // Static Helpers
18479
+ //////////////////////////////////////////////////////////////////////////////
18480
+ static currentCiphertextVersion() {
18481
+ return FhevmHandle.CURRENT_CIPHERTEXT_VERSION;
18482
+ }
18483
+ //////////////////////////////////////////////////////////////////////////////
18484
+ // Private Helpers
18485
+ //////////////////////////////////////////////////////////////////////////////
18100
18486
  /**
18101
18487
  * blobHashBytes32 = keccak256(ciphertextWithZKProof)
18102
18488
  */
18103
18489
  static _computeInputHash21(blobHashBytes32, aclAddress, chainId, index) {
18104
18490
  /*
18105
18491
  https://github.com/zama-ai/fhevm/blob/8ffbd5906ab3d57af178e049930e3fc065c9d4b3/coprocessor/fhevm-engine/zkproof-worker/src/verifier.rs#L431C7-L431C8
18106
-
18492
+
18107
18493
  handle_hash = Bytes("ZK-w_hdl") + blobHash 32 Bytes + index 1 Byte + aclAddress 20 Bytes + chainId 32 bytes
18108
18494
  ===========================================================================================================
18109
18495
 
18110
18496
  const HANDLE_HASH_DOMAIN_SEPARATOR: [u8; 8] = *b"ZK-w_hdl";
18111
-
18497
+
18112
18498
  let mut handle_hash = Keccak256::new();
18113
18499
  handle_hash.update(HANDLE_HASH_DOMAIN_SEPARATOR);
18114
18500
  handle_hash.update(blob_hash);
@@ -18129,62 +18515,12 @@ class FhevmHandle {
18129
18515
  assertIsUint64(chainId);
18130
18516
  const encryptionIndexByte1 = new Uint8Array([index]);
18131
18517
  const aclContractAddressBytes20 = checksummedAddressToBytes20(aclAddress);
18132
- const chainIdBytes32 = uint32ToBytes32(chainId);
18518
+ const chainIdBytes32 = numberToBytes32(chainId);
18133
18519
  const encoder = new TextEncoder();
18134
18520
  const domainSepBytes = encoder.encode(FhevmHandle.HANDLE_HASH_DOMAIN_SEPARATOR);
18135
- return keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
18136
- }
18137
- toBytes32() {
18138
- assertRelayer((this._index === undefined && this._computed) ||
18139
- (this._index !== undefined && this._index < 255 && !this._computed));
18140
- const chainId32Bytes = uint32ToBytes32(this._chainId);
18141
- const chainId8Bytes = chainId32Bytes.subarray(24, 32);
18142
- const handleHash = hexToBytes(this._hash21);
18143
- const handleBytes32AsBytes = new Uint8Array(32);
18144
- handleBytes32AsBytes.set(handleHash, 0);
18145
- handleBytes32AsBytes[21] = this._index === undefined ? 255 : this._index;
18146
- handleBytes32AsBytes.set(chainId8Bytes, 22);
18147
- handleBytes32AsBytes[30] = this._fheTypeId;
18148
- handleBytes32AsBytes[31] = this._version;
18149
- return handleBytes32AsBytes;
18150
- }
18151
- toBytes32Hex() {
18152
- return bytesToHex(this.toBytes32());
18153
- }
18154
- static checkHandleHex(handle) {
18155
- if (!isBytes32Hex(handle)) {
18156
- throw new FhevmHandleError({ handle });
18157
- }
18158
- }
18159
- static isFheTypeId(value) {
18160
- switch (value) {
18161
- case 0:
18162
- // 1: euint4 is deprecated
18163
- case 2:
18164
- case 3:
18165
- case 4:
18166
- case 5:
18167
- case 6:
18168
- case 7:
18169
- case 8:
18170
- return true;
18171
- default:
18172
- return false;
18173
- }
18174
- }
18175
- static getFheTypeId(handle) {
18176
- if (!isBytes32Hex(handle)) {
18177
- throw new FhevmHandleError({ handle });
18178
- }
18179
- const hexPair = handle.slice(-4, -2).toLowerCase();
18180
- const typeDiscriminant = parseInt(hexPair, 16);
18181
- if (!FhevmHandle.isFheTypeId(typeDiscriminant)) {
18182
- throw new FhevmHandleError({
18183
- handle,
18184
- message: `FHEVM Handle "${handle}" is invalid. Unknown FheType: ${typeDiscriminant}`,
18185
- });
18186
- }
18187
- return typeDiscriminant;
18521
+ const hashBytes32Hex = keccak256(concatBytes(domainSepBytes, blobHashBytes32, encryptionIndexByte1, aclContractAddressBytes20, chainIdBytes32));
18522
+ // Truncate to 21 bytes (0x + 42 hex chars)
18523
+ return hashBytes32Hex.slice(0, 2 + 2 * 21);
18188
18524
  }
18189
18525
  }
18190
18526
 
@@ -18193,6 +18529,89 @@ const getAddress = (value) => getAddress$2(value);
18193
18529
  const currentCiphertextVersion = () => {
18194
18530
  return 0;
18195
18531
  };
18532
+ async function requestCiphertextWithZKProofVerification({ bits, ciphertext, contractAddress, userAddress, aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerProvider, coprocessorSigners, thresholdCoprocessorSigners, extraData, options, }) {
18533
+ const payload = {
18534
+ contractAddress,
18535
+ userAddress,
18536
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
18537
+ contractChainId: ('0x' + chainId.toString(16)),
18538
+ extraData,
18539
+ };
18540
+ const json = await relayerProvider.fetchPostInputProof(payload, options);
18541
+ if (!isFhevmRelayerInputProofResponse(json)) {
18542
+ throwRelayerInternalError('INPUT_PROOF', json);
18543
+ }
18544
+ const fhevmHandles = FhevmHandle.fromZKProof({
18545
+ ciphertextWithZKProof: ciphertext,
18546
+ chainId,
18547
+ aclAddress: aclContractAddress,
18548
+ ciphertextVersion: currentCiphertextVersion(),
18549
+ fheTypeEncryptionBitwidths: bits,
18550
+ });
18551
+ const handles = fhevmHandles.map((h) => h.toBytes32());
18552
+ const result = json;
18553
+ // Note that the hex strings returned by the relayer do have have the 0x prefix
18554
+ if (result.handles && result.handles.length > 0) {
18555
+ const responseHandles = result.handles.map(hexToBytes);
18556
+ if (handles.length != responseHandles.length) {
18557
+ throw new Error(`Incorrect Handles list sizes: (expected) ${handles.length} != ${responseHandles.length} (received)`);
18558
+ }
18559
+ for (let index = 0; index < handles.length; index += 1) {
18560
+ let handle = handles[index];
18561
+ let responseHandle = responseHandles[index];
18562
+ let expected = bytesToHexNo0x(handle);
18563
+ let current = bytesToHexNo0x(responseHandle);
18564
+ if (expected !== current) {
18565
+ throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
18566
+ }
18567
+ }
18568
+ }
18569
+ const signatures = result.signatures;
18570
+ // verify signatures for inputs:
18571
+ const domain = {
18572
+ name: 'InputVerification',
18573
+ version: '1',
18574
+ chainId: gatewayChainId,
18575
+ verifyingContract: verifyingContractAddressInputVerification,
18576
+ };
18577
+ const types = {
18578
+ CiphertextVerification: [
18579
+ { name: 'ctHandles', type: 'bytes32[]' },
18580
+ { name: 'userAddress', type: 'address' },
18581
+ { name: 'contractAddress', type: 'address' },
18582
+ { name: 'contractChainId', type: 'uint256' },
18583
+ { name: 'extraData', type: 'bytes' },
18584
+ ],
18585
+ };
18586
+ const recoveredAddresses = signatures.map((signature) => {
18587
+ const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
18588
+ const recoveredAddress = ethers.verifyTypedData(domain, types, {
18589
+ ctHandles: handles,
18590
+ userAddress,
18591
+ contractAddress,
18592
+ contractChainId: chainId,
18593
+ extraData,
18594
+ }, sig);
18595
+ return recoveredAddress;
18596
+ });
18597
+ const thresholdReached = isThresholdReached$1(coprocessorSigners, recoveredAddresses, thresholdCoprocessorSigners);
18598
+ if (!thresholdReached) {
18599
+ throw Error('Coprocessor signers threshold is not reached');
18600
+ }
18601
+ // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
18602
+ let inputProof = numberToHexNo0x(handles.length);
18603
+ const numSigners = signatures.length;
18604
+ inputProof += numberToHexNo0x(numSigners);
18605
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
18606
+ listHandlesStr.map((handle) => (inputProof += handle));
18607
+ signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
18608
+ // Append the extra data to the input proof
18609
+ inputProof += extraData.slice(2);
18610
+ return {
18611
+ handles,
18612
+ inputProof: hexToBytes(inputProof),
18613
+ };
18614
+ }
18196
18615
  function isThresholdReached$1(coprocessorSigners, recoveredAddresses, threshold) {
18197
18616
  const addressMap = new Map();
18198
18617
  recoveredAddresses.forEach((address, index) => {
@@ -18276,8 +18695,15 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
18276
18695
  getBits() {
18277
18696
  return input.getBits();
18278
18697
  },
18279
- getCiphertextWithInputVerification() {
18280
- return input.encrypt();
18698
+ generateZKProof() {
18699
+ return {
18700
+ chainId,
18701
+ aclContractAddress: aclContractAddress,
18702
+ userAddress: userAddress,
18703
+ contractAddress: contractAddress,
18704
+ ciphertextWithZkProof: input.encrypt(),
18705
+ bits: input.getBits(),
18706
+ };
18281
18707
  },
18282
18708
  encrypt: async (options) => {
18283
18709
  const extraData = '0x00';
@@ -18286,7 +18712,7 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
18286
18712
  const payload = {
18287
18713
  contractAddress: getAddress(contractAddress),
18288
18714
  userAddress: getAddress(userAddress),
18289
- ciphertextWithInputVerification: toHexString(ciphertext),
18715
+ ciphertextWithInputVerification: bytesToHexNo0x(ciphertext),
18290
18716
  contractChainId: ('0x' + chainId.toString(16)),
18291
18717
  extraData,
18292
18718
  };
@@ -18315,8 +18741,8 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
18315
18741
  for (let index = 0; index < handles.length; index += 1) {
18316
18742
  let handle = handles[index];
18317
18743
  let responseHandle = responseHandles[index];
18318
- let expected = toHexString(handle);
18319
- let current = toHexString(responseHandle);
18744
+ let expected = bytesToHexNo0x(handle);
18745
+ let current = bytesToHexNo0x(responseHandle);
18320
18746
  if (expected !== current) {
18321
18747
  throw new Error(`Incorrect Handle ${index}: (expected) ${expected} != ${current} (received)`);
18322
18748
  }
@@ -18355,10 +18781,10 @@ const createRelayerEncryptedInput = (aclContractAddress, verifyingContractAddres
18355
18781
  throw Error('Coprocessor signers threshold is not reached');
18356
18782
  }
18357
18783
  // inputProof is len(list_handles) + numCoprocessorSigners + list_handles + signatureCoprocessorSigners (1+1+NUM_HANDLES*32+65*numSigners)
18358
- let inputProof = numberToHex(handles.length);
18784
+ let inputProof = numberToHexNo0x(handles.length);
18359
18785
  const numSigners = signatures.length;
18360
- inputProof += numberToHex(numSigners);
18361
- const listHandlesStr = handles.map((i) => toHexString(i));
18786
+ inputProof += numberToHexNo0x(numSigners);
18787
+ const listHandlesStr = handles.map((i) => bytesToHexNo0x(i));
18362
18788
  listHandlesStr.map((handle) => (inputProof += handle));
18363
18789
  signatures.map((signature) => (inputProof += signature.slice(2))); // removes the '0x' prefix from the `signature` string
18364
18790
  // Append the extra data to the input proof
@@ -18411,7 +18837,7 @@ function abiEncodeClearValues(clearValues) {
18411
18837
  const abiValues = [];
18412
18838
  for (let i = 0; i < handlesBytes32Hex.length; ++i) {
18413
18839
  const handle = handlesBytes32Hex[i];
18414
- const handleType = FhevmHandle.getFheTypeId(handle);
18840
+ const handleType = FhevmHandle.parse(handle).fheTypeId;
18415
18841
  let clearTextValue = clearValues[handle];
18416
18842
  if (typeof clearTextValue === 'boolean') {
18417
18843
  clearTextValue = clearTextValue ? '0x01' : '0x00';
@@ -18474,24 +18900,23 @@ function buildDecryptionProof(kmsSignatures, extraData) {
18474
18900
  return decryptionProof;
18475
18901
  }
18476
18902
  function deserializeClearValues(handles, decryptedResult) {
18477
- let typesList = [];
18903
+ let fheTypeIdList = [];
18478
18904
  for (const handle of handles) {
18479
- const typeDiscriminant = FhevmHandle.getFheTypeId(handle);
18480
- assertRelayer(FhevmHandle.isFheTypeId(typeDiscriminant));
18481
- typesList.push(typeDiscriminant);
18905
+ const typeDiscriminant = FhevmHandle.parse(handle).fheTypeId;
18906
+ fheTypeIdList.push(typeDiscriminant);
18482
18907
  }
18483
18908
  const restoredEncoded = '0x' +
18484
18909
  '00'.repeat(32) + // dummy requestID (ignored)
18485
18910
  decryptedResult.slice(2) +
18486
18911
  '00'.repeat(32); // dummy empty bytes[] length (ignored)
18487
- const abiTypes = typesList.map((t) => {
18488
- const abiType = FhevmHandle.FheTypeIdToSolidityPrimitiveType[t]; // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
18912
+ const abiTypes = fheTypeIdList.map((t) => {
18913
+ const abiType = solidityPrimitiveTypeNameFromFheTypeId(t); // all types are valid because this was supposedly checked already inside the `checkEncryptedBits` function
18489
18914
  return abiType;
18490
18915
  });
18491
18916
  const coder = new AbiCoder();
18492
18917
  const decoded = coder.decode(['uint256', ...abiTypes, 'bytes[]'], restoredEncoded);
18493
18918
  // strip dummy first/last element
18494
- const rawValues = decoded.slice(1, 1 + typesList.length);
18919
+ const rawValues = decoded.slice(1, 1 + fheTypeIdList.length);
18495
18920
  const results = {};
18496
18921
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
18497
18922
  return results;
@@ -18499,12 +18924,13 @@ function deserializeClearValues(handles, decryptedResult) {
18499
18924
  const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, verifyingContractAddress, aclContractAddress, relayerProvider, provider, defaultOptions) => async (_handles, options) => {
18500
18925
  const extraData = '0x00';
18501
18926
  const acl = new ethers.Contract(aclContractAddress, aclABI, provider);
18927
+ // This will be replaced by new sanitize classes
18502
18928
  let handles;
18503
18929
  try {
18504
18930
  handles = await Promise.all(_handles.map(async (_handle) => {
18505
18931
  const handle = typeof _handle === 'string'
18506
- ? toHexString(hexToBytes(_handle), true)
18507
- : toHexString(_handle, true);
18932
+ ? bytesToHex(hexToBytes(_handle))
18933
+ : bytesToHex(_handle);
18508
18934
  const isAllowedForDecryption = await acl.isAllowedForDecryption(handle);
18509
18935
  if (!isAllowedForDecryption) {
18510
18936
  throw new Error(`Handle ${handle} is not allowed for public decryption!`);
@@ -18662,8 +19088,8 @@ const createEIP712 = (verifyingContract, contractsChainId) => (publicKey, contra
18662
19088
  const generateKeypair = () => {
18663
19089
  const keypair = TKMS.ml_kem_pke_keygen();
18664
19090
  return {
18665
- publicKey: toHexString(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
18666
- privateKey: toHexString(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
19091
+ publicKey: bytesToHexNo0x(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
19092
+ privateKey: bytesToHexNo0x(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
18667
19093
  };
18668
19094
  };
18669
19095
 
@@ -19327,7 +19753,28 @@ function assertIsRelayerV2GetResponseQueued(value, name) {
19327
19753
  assertRecordStringProperty(value, 'requestId', name);
19328
19754
  }
19329
19755
 
19756
+ class RelayerV2TimeoutError extends RelayerV2RequestErrorBase {
19757
+ constructor(params) {
19758
+ super({
19759
+ ...params,
19760
+ name: 'RelayerV2TimeoutError',
19761
+ message: `Request timed out after ${params.timeoutMs}ms`,
19762
+ });
19763
+ }
19764
+ }
19765
+
19766
+ class RelayerV2AbortError extends RelayerV2RequestErrorBase {
19767
+ constructor(params) {
19768
+ super({
19769
+ ...params,
19770
+ name: 'RelayerV2AbortError',
19771
+ message: `Request aborted`,
19772
+ });
19773
+ }
19774
+ }
19775
+
19330
19776
  class RelayerV2AsyncRequest {
19777
+ _fetchMethod;
19331
19778
  _jobId;
19332
19779
  _jobIdTimestamp;
19333
19780
  _state;
@@ -19342,17 +19789,18 @@ class RelayerV2AsyncRequest {
19342
19789
  _retryAfterTimeoutID;
19343
19790
  _url;
19344
19791
  _payload;
19345
- _fhevmInstanceOptions;
19792
+ _fhevmAuth;
19346
19793
  _retryAfterTimeoutPromiseFuncReject;
19347
19794
  _onProgress;
19348
- _requestMaxDurationInSecs;
19795
+ _requestMaxDurationInMs;
19349
19796
  _requestStartTimestamp;
19350
19797
  _requestGlobalTimeoutID;
19351
19798
  _throwErrorIfNoRetryAfter;
19352
- static DEFAULT_RETRY_AFTER_SECS = 2;
19353
- static DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS = 60 * 60;
19354
- static MAX_GET_RETRY = 100;
19355
- static MAX_POST_RETRY = 100;
19799
+ static DEFAULT_RETRY_AFTER_MS = 2500;
19800
+ static MINIMUM_RETRY_AFTER_MS = 1000;
19801
+ static DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS = 60 * 60 * 1000; // 1 hour
19802
+ static MAX_GET_RETRY = 60 * 30; // number of default retries in 1 hour (30 retries/min)
19803
+ static MAX_POST_RETRY = RelayerV2AsyncRequest.MAX_GET_RETRY;
19356
19804
  constructor(params) {
19357
19805
  if (params.relayerOperation !== 'INPUT_PROOF' &&
19358
19806
  params.relayerOperation !== 'PUBLIC_DECRYPT' &&
@@ -19369,14 +19817,14 @@ class RelayerV2AsyncRequest {
19369
19817
  this._internalAbortController = new AbortController();
19370
19818
  this._internalAbortSignal = this._internalAbortController.signal;
19371
19819
  this._internalAbortSignal.addEventListener('abort', this._handleInternalSignalAbort);
19372
- this._externalAbortSignal = params.signal;
19820
+ this._externalAbortSignal = params.options?.signal;
19373
19821
  if (this._externalAbortSignal) {
19374
19822
  this._externalAbortSignal.addEventListener('abort', this._handleExternalSignalAbort);
19375
19823
  }
19376
19824
  this._url = params.url;
19377
19825
  this._payload = params.payload;
19378
- this._fhevmInstanceOptions = params.instanceOptions;
19379
- this._onProgress = params.onProgress;
19826
+ this._fhevmAuth = params.options?.auth;
19827
+ this._onProgress = params.options?.onProgress;
19380
19828
  this._state = {
19381
19829
  aborted: false,
19382
19830
  canceled: false,
@@ -19385,6 +19833,7 @@ class RelayerV2AsyncRequest {
19385
19833
  running: false,
19386
19834
  succeeded: false,
19387
19835
  terminated: false,
19836
+ timeout: false,
19388
19837
  };
19389
19838
  this._retryCount = 0;
19390
19839
  this._retryAfterTimeoutID = undefined;
@@ -19392,9 +19841,9 @@ class RelayerV2AsyncRequest {
19392
19841
  this._terminateReason = undefined;
19393
19842
  this._publicAPINoReentrancy = false;
19394
19843
  this._throwErrorIfNoRetryAfter = params.throwErrorIfNoRetryAfter ?? false;
19395
- this._requestMaxDurationInSecs =
19396
- params.timeoutInSeconds ??
19397
- RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_SECS;
19844
+ this._requestMaxDurationInMs =
19845
+ params.options?.timeout ??
19846
+ RelayerV2AsyncRequest.DEFAULT_GLOBAL_REQUEST_TIMEOUT_MS;
19398
19847
  }
19399
19848
  //////////////////////////////////////////////////////////////////////////////
19400
19849
  // Public API: run
@@ -19436,6 +19885,12 @@ class RelayerV2AsyncRequest {
19436
19885
  state: { ...this._state },
19437
19886
  });
19438
19887
  }
19888
+ if (this._state.timeout) {
19889
+ throw new RelayerV2StateError({
19890
+ message: `Relayer.run() failed. Request already timeout.`,
19891
+ state: { ...this._state },
19892
+ });
19893
+ }
19439
19894
  if (this._externalAbortSignal?.aborted === true) {
19440
19895
  throw new RelayerV2StateError({
19441
19896
  message: `Relayer.run() failed. External AbortSignal already aborted (reason:${this._externalAbortSignal?.reason}).`,
@@ -19456,7 +19911,7 @@ class RelayerV2AsyncRequest {
19456
19911
  }
19457
19912
  this._state.running = true;
19458
19913
  this._requestStartTimestamp = Date.now();
19459
- this._setGlobalRequestTimeout(this._requestMaxDurationInSecs * 1000);
19914
+ this._setGlobalRequestTimeout(this._requestMaxDurationInMs);
19460
19915
  try {
19461
19916
  const json = await this._runPostLoop();
19462
19917
  this._state.succeeded = true;
@@ -19527,6 +19982,12 @@ class RelayerV2AsyncRequest {
19527
19982
  get failed() {
19528
19983
  return this._state.failed;
19529
19984
  }
19985
+ get aborted() {
19986
+ return this._state.aborted;
19987
+ }
19988
+ get timeout() {
19989
+ return this._state.timeout;
19990
+ }
19530
19991
  get succeeded() {
19531
19992
  return this._state.succeeded;
19532
19993
  }
@@ -19547,6 +20008,8 @@ class RelayerV2AsyncRequest {
19547
20008
  //////////////////////////////////////////////////////////////////////////////
19548
20009
  // POST : 202 | 400 | 429 | 500 | 503
19549
20010
  async _runPostLoop() {
20011
+ this._assert(this._fetchMethod === undefined, 'this._fetchMethod === undefined');
20012
+ this._fetchMethod = 'POST';
19550
20013
  // No infinite loop!
19551
20014
  let i = 0;
19552
20015
  while (i < RelayerV2AsyncRequest.MAX_POST_RETRY) {
@@ -19582,9 +20045,7 @@ class RelayerV2AsyncRequest {
19582
20045
  bodyJson: safeJSONstringify(bodyJson),
19583
20046
  });
19584
20047
  }
19585
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
19586
- if (retry_after_sec < 1)
19587
- retry_after_sec = 1;
20048
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
19588
20049
  // Debug: will throw an assert failed error if jobId has already been set
19589
20050
  this._setJobIdOnce(bodyJson.result.jobId);
19590
20051
  // Async onProgress callback
@@ -19597,11 +20058,10 @@ class RelayerV2AsyncRequest {
19597
20058
  jobId: this.jobId,
19598
20059
  operation: this._relayerOperation,
19599
20060
  retryCount: this._retryCount,
19600
- retryAfter: retry_after_sec,
20061
+ retryAfterMs,
19601
20062
  elapsed,
19602
20063
  });
19603
- // Wait if needed (minimum 1s)
19604
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
20064
+ await this._setRetryAfterTimeout(retryAfterMs);
19605
20065
  const json = await this._runGetLoop();
19606
20066
  return json;
19607
20067
  }
@@ -19647,22 +20107,20 @@ class RelayerV2AsyncRequest {
19647
20107
  bodyJson: safeJSONstringify(bodyJson),
19648
20108
  });
19649
20109
  }
19650
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
19651
- if (retry_after_sec < 1)
19652
- retry_after_sec = 1;
20110
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
19653
20111
  // Async onProgress callback
19654
20112
  this._postAsyncOnProgressCallback({
19655
20113
  type: 'ratelimited',
19656
20114
  url: this._url,
19657
20115
  method: 'POST',
19658
20116
  status: responseStatus,
19659
- retryAfter: retry_after_sec,
20117
+ retryAfterMs,
19660
20118
  retryCount: this._retryCount,
19661
20119
  elapsed,
19662
- message: bodyJson.error.message,
20120
+ relayerApiError: bodyJson.error,
19663
20121
  });
19664
20122
  // Wait if needed (minimum 1s)
19665
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
20123
+ await this._setRetryAfterTimeout(retryAfterMs);
19666
20124
  continue;
19667
20125
  }
19668
20126
  // RelayerV2ResponseFailed
@@ -19741,8 +20199,10 @@ class RelayerV2AsyncRequest {
19741
20199
  // GET: 200 | 202 | 404 | 500 | 503 | 504
19742
20200
  // GET is not rate-limited, therefore there is not 429 error
19743
20201
  async _runGetLoop() {
20202
+ this._assert(this._fetchMethod === 'POST', "this._fetchMethod === 'POST'");
19744
20203
  this._assert(this._jobId !== undefined, 'this._jobId !== undefined');
19745
20204
  this._assert(this._jobIdTimestamp !== undefined, 'this._jobIdTimestamp !== undefined');
20205
+ this._fetchMethod = 'GET';
19746
20206
  let i = 0;
19747
20207
  while (i < RelayerV2AsyncRequest.MAX_GET_RETRY) {
19748
20208
  ++i;
@@ -19852,9 +20312,7 @@ class RelayerV2AsyncRequest {
19852
20312
  bodyJson: safeJSONstringify(bodyJson),
19853
20313
  });
19854
20314
  }
19855
- let retry_after_sec = this._getRetryAfterHeaderValueInSecs(response);
19856
- if (retry_after_sec < 1)
19857
- retry_after_sec = 1;
20315
+ const retryAfterMs = this._getRetryAfterHeaderValueInMs(response);
19858
20316
  // Async onProgress callback
19859
20317
  this._postAsyncOnProgressCallback({
19860
20318
  type: 'queued',
@@ -19864,12 +20322,12 @@ class RelayerV2AsyncRequest {
19864
20322
  requestId: bodyJson.requestId,
19865
20323
  operation: this._relayerOperation,
19866
20324
  jobId: this.jobId,
19867
- retryAfter: retry_after_sec,
20325
+ retryAfterMs,
19868
20326
  retryCount: this._retryCount,
19869
20327
  elapsed,
19870
20328
  });
19871
20329
  // Wait if needed (minimum 1s)
19872
- await this._setRetryAfterTimeout(retry_after_sec * 1000);
20330
+ await this._setRetryAfterTimeout(retryAfterMs);
19873
20331
  continue;
19874
20332
  }
19875
20333
  case 400: {
@@ -20021,17 +20479,20 @@ class RelayerV2AsyncRequest {
20021
20479
  return bodyJson;
20022
20480
  }
20023
20481
  //////////////////////////////////////////////////////////////////////////////
20024
- _getRetryAfterHeaderValueInSecs(response) {
20482
+ _getRetryAfterHeaderValueInMs(response) {
20025
20483
  if (!response.headers.has('Retry-After')) {
20026
20484
  if (this._throwErrorIfNoRetryAfter) {
20027
20485
  throw new Error(`Missing 'Retry-After' header key`);
20028
20486
  }
20029
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
20487
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
20030
20488
  }
20031
20489
  try {
20032
20490
  const n = Number.parseInt(response.headers.get('Retry-After'));
20033
20491
  if (isUint(n)) {
20034
- return n;
20492
+ const ms = n * 1000;
20493
+ return ms < RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
20494
+ ? RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS
20495
+ : ms;
20035
20496
  }
20036
20497
  }
20037
20498
  catch {
@@ -20040,7 +20501,7 @@ class RelayerV2AsyncRequest {
20040
20501
  if (this._throwErrorIfNoRetryAfter) {
20041
20502
  throw new Error(`Invalid 'Retry-After' header key`);
20042
20503
  }
20043
- return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_SECS;
20504
+ return RelayerV2AsyncRequest.DEFAULT_RETRY_AFTER_MS;
20044
20505
  }
20045
20506
  //////////////////////////////////////////////////////////////////////////////
20046
20507
  // JobId
@@ -20079,7 +20540,7 @@ class RelayerV2AsyncRequest {
20079
20540
  this._assert(this._jobId === undefined, 'this._jobId === undefined');
20080
20541
  this._assert(!this._state.terminated, '!this._state.terminated');
20081
20542
  this._assert(!this._state.fetching, '!this._state.fetching');
20082
- this._trace('_fetchPost', 'enter');
20543
+ this._trace('_fetchPost', this._url);
20083
20544
  const init = setAuth({
20084
20545
  method: 'POST',
20085
20546
  headers: {
@@ -20091,7 +20552,7 @@ class RelayerV2AsyncRequest {
20091
20552
  ...(this._internalAbortSignal
20092
20553
  ? { signal: this._internalAbortSignal }
20093
20554
  : {}),
20094
- }, this._fhevmInstanceOptions?.auth);
20555
+ }, this._fhevmAuth);
20095
20556
  this._state.fetching = true;
20096
20557
  let response;
20097
20558
  try {
@@ -20218,7 +20679,18 @@ class RelayerV2AsyncRequest {
20218
20679
  if (signal.reason !== 'cancel') {
20219
20680
  this._assert(!this._state.canceled, '!this._state.canceled');
20220
20681
  }
20221
- this._terminate('abort');
20682
+ this._postAsyncOnProgressCallback({
20683
+ type: 'abort',
20684
+ url: this._url,
20685
+ ...(this._jobId ? { jobId: this._jobId } : {}),
20686
+ operation: this._relayerOperation,
20687
+ retryCount: this._retryCount,
20688
+ });
20689
+ this._terminate('abort', new RelayerV2AbortError({
20690
+ operation: this._relayerOperation,
20691
+ jobId: this._jobId,
20692
+ url: this._url,
20693
+ }));
20222
20694
  };
20223
20695
  //////////////////////////////////////////////////////////////////////////////
20224
20696
  // Terminate
@@ -20242,7 +20714,7 @@ class RelayerV2AsyncRequest {
20242
20714
  this._terminateReason = reason;
20243
20715
  this._terminateError = error;
20244
20716
  this._state.terminated = true;
20245
- this._tryClearRetryAfterTimeout();
20717
+ this._tryClearRetryAfterTimeout(error);
20246
20718
  this._tryClearGlobalRequestTimeout();
20247
20719
  const is = this._internalAbortSignal;
20248
20720
  const es = this._externalAbortSignal;
@@ -20264,7 +20736,7 @@ class RelayerV2AsyncRequest {
20264
20736
  // Debug
20265
20737
  this._assert(!this._state.terminated, '!this._state.terminated');
20266
20738
  this._assert(this._retryAfterTimeoutID === undefined, 'this._retryAfterTimeoutID === undefined');
20267
- this._assert(delayMs >= 1000, 'delayMs >= 1000');
20739
+ this._assert(delayMs >= RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS, `delayMs >= ${RelayerV2AsyncRequest.MINIMUM_RETRY_AFTER_MS}`);
20268
20740
  this._trace('_setRetryAfterTimeout', `delayMs=${delayMs}`);
20269
20741
  if (this._retryAfterTimeoutID !== undefined) {
20270
20742
  return Promise.reject(new Error(`retry-after already running.`));
@@ -20284,7 +20756,7 @@ class RelayerV2AsyncRequest {
20284
20756
  return p;
20285
20757
  }
20286
20758
  //////////////////////////////////////////////////////////////////////////////
20287
- _tryClearRetryAfterTimeout() {
20759
+ _tryClearRetryAfterTimeout(error) {
20288
20760
  if (this._retryAfterTimeoutID === undefined) {
20289
20761
  // Debug
20290
20762
  this._assert(this._retryAfterTimeoutPromiseFuncReject === undefined, 'this._retryAfterTimeoutPromiseFuncReject === undefined');
@@ -20295,7 +20767,8 @@ class RelayerV2AsyncRequest {
20295
20767
  this._retryAfterTimeoutID = undefined;
20296
20768
  this._retryAfterTimeoutPromiseFuncReject = undefined;
20297
20769
  clearTimeout(tid);
20298
- reject(new Error('_tryClearRetryAfterTimeout'));
20770
+ // Calling reject will
20771
+ reject(error ?? new Error('_tryClearRetryAfterTimeout'));
20299
20772
  }
20300
20773
  //////////////////////////////////////////////////////////////////////////////
20301
20774
  // Global Request Timeout
@@ -20310,7 +20783,24 @@ class RelayerV2AsyncRequest {
20310
20783
  this._requestGlobalTimeoutID = setTimeout(callback, delayMs);
20311
20784
  }
20312
20785
  _handleGlobalRequestTimeout() {
20313
- this._terminate('timeout');
20786
+ this._state.timeout = true;
20787
+ // Debug state-check guards:
20788
+ this._assert(this instanceof RelayerV2AsyncRequest, `this instanceof RelayerV2AsyncRequest`);
20789
+ this._assert(!this._state.terminated, `!this._state.terminated`);
20790
+ this._assert(!this._state.timeout, '!this._state.timeout');
20791
+ this._postAsyncOnProgressCallback({
20792
+ type: 'timeout',
20793
+ url: this._url,
20794
+ ...(this._jobId ? { jobId: this._jobId } : {}),
20795
+ operation: this._relayerOperation,
20796
+ retryCount: this._retryCount,
20797
+ });
20798
+ this._terminate('timeout', new RelayerV2TimeoutError({
20799
+ operation: this._relayerOperation,
20800
+ jobId: this._jobId,
20801
+ url: this._url,
20802
+ timeoutMs: this._requestMaxDurationInMs,
20803
+ }));
20314
20804
  }
20315
20805
  _tryClearGlobalRequestTimeout() {
20316
20806
  if (this._requestGlobalTimeoutID === undefined) {
@@ -20518,37 +21008,34 @@ class RelayerV2Provider extends AbstractRelayerProvider {
20518
21008
  const response = await this.fetchGetKeyUrlV2();
20519
21009
  return toRelayerV1KeyUrlResponse(response);
20520
21010
  }
20521
- async fetchPostInputProof(payload, instanceOptions, fetchOptions) {
21011
+ async fetchPostInputProof(payload, options) {
20522
21012
  const request = new RelayerV2AsyncRequest({
20523
21013
  relayerOperation: 'INPUT_PROOF',
20524
21014
  url: this.inputProof,
20525
21015
  payload,
20526
- instanceOptions,
20527
- ...fetchOptions,
21016
+ options,
20528
21017
  });
20529
21018
  const result = (await request.run());
20530
21019
  assertIsRelayerInputProofResult(result, 'fetchPostInputProof()');
20531
21020
  return result;
20532
21021
  }
20533
- async fetchPostPublicDecrypt(payload, instanceOptions, fetchOptions) {
21022
+ async fetchPostPublicDecrypt(payload, options) {
20534
21023
  const request = new RelayerV2AsyncRequest({
20535
21024
  relayerOperation: 'PUBLIC_DECRYPT',
20536
21025
  url: this.publicDecrypt,
20537
21026
  payload,
20538
- instanceOptions,
20539
- ...fetchOptions,
21027
+ options,
20540
21028
  });
20541
21029
  const result = await request.run();
20542
21030
  assertIsRelayerPublicDecryptResult(result, 'fetchPostPublicDecrypt()');
20543
21031
  return result;
20544
21032
  }
20545
- async fetchPostUserDecrypt(payload, instanceOptions, fetchOptions) {
21033
+ async fetchPostUserDecrypt(payload, options) {
20546
21034
  const request = new RelayerV2AsyncRequest({
20547
21035
  relayerOperation: 'USER_DECRYPT',
20548
21036
  url: this.userDecrypt,
20549
21037
  payload,
20550
- instanceOptions,
20551
- ...fetchOptions,
21038
+ options,
20552
21039
  });
20553
21040
  const result = (await request.run());
20554
21041
  assertIsRelayerUserDecryptResult(result.result, 'fetchPostUserDecrypt()');
@@ -20556,6 +21043,16 @@ class RelayerV2Provider extends AbstractRelayerProvider {
20556
21043
  }
20557
21044
  }
20558
21045
 
21046
+ class TFHECrsError extends RelayerErrorBase {
21047
+ constructor({ message, cause }) {
21048
+ super({
21049
+ message,
21050
+ name: 'TFHECrsError',
21051
+ ...(cause ? { cause: ensureError(cause) } : {}),
21052
+ });
21053
+ }
21054
+ }
21055
+
20559
21056
  class AbstractRelayerFhevm {
20560
21057
  }
20561
21058
 
@@ -20570,6 +21067,15 @@ class TFHECrs {
20570
21067
  this._bits = params.bits;
20571
21068
  this._srcUrl = params.srcUrl;
20572
21069
  }
21070
+ get id() {
21071
+ return this._id;
21072
+ }
21073
+ get bits() {
21074
+ return this._bits;
21075
+ }
21076
+ get srcUrl() {
21077
+ return this._srcUrl;
21078
+ }
20573
21079
  /*
20574
21080
  {
20575
21081
  id: string,
@@ -20672,19 +21178,57 @@ class TFHECrs {
20672
21178
  return TFHECrs._fromUrl(params);
20673
21179
  }
20674
21180
  else {
20675
- throw new Error('Invalid public key (deserialization failed)');
21181
+ throw new TFHECrsError({
21182
+ message: 'Invalid public key (deserialization failed)',
21183
+ });
20676
21184
  }
20677
21185
  }
21186
+ /*
21187
+ {
21188
+ id: string;
21189
+ data: Uint8Array;
21190
+ bits: number;
21191
+ srcUrl?: string;
21192
+ }
21193
+ */
20678
21194
  static fromBytes(params) {
20679
21195
  try {
20680
21196
  TFHECrs.assertKeyBytesType(params, 'arg');
20681
21197
  return TFHECrs._fromBytes(params);
20682
21198
  }
20683
21199
  catch (e) {
20684
- throw new Error('Invalid public key (deserialization failed)', {
21200
+ throw new TFHECrsError({
21201
+ message: 'Invalid public key (deserialization failed)',
21202
+ cause: e,
21203
+ });
21204
+ }
21205
+ }
21206
+ /*
21207
+ {
21208
+ id: string;
21209
+ data: BytesHex;
21210
+ bits: number;
21211
+ srcUrl?: string;
21212
+ }
21213
+ */
21214
+ static fromBytesHex(params) {
21215
+ let data;
21216
+ try {
21217
+ assertRecordStringProperty(params, 'data', 'arg');
21218
+ data = hexToBytesFaster(params.data, true /* strict */);
21219
+ }
21220
+ catch (e) {
21221
+ throw new TFHECrsError({
21222
+ message: 'Invalid public key (deserialization failed)',
20685
21223
  cause: e,
20686
21224
  });
20687
21225
  }
21226
+ return TFHECrs.fromBytes({
21227
+ id: params?.id,
21228
+ bits: params?.bits,
21229
+ srcUrl: params?.srcUrl,
21230
+ data,
21231
+ });
20688
21232
  }
20689
21233
  static _fromBytes(params) {
20690
21234
  const _params = {
@@ -20701,7 +21245,50 @@ class TFHECrs {
20701
21245
  return TFHECrs._fromPublicParamsBytes(params);
20702
21246
  }
20703
21247
  catch (e) {
20704
- throw new Error('Invalid public key (deserialization failed)', {
21248
+ throw new TFHECrsError({
21249
+ message: 'Invalid public key (deserialization failed)',
21250
+ cause: e,
21251
+ });
21252
+ }
21253
+ }
21254
+ static fromBitsPublicParamsBytes(bits, params) {
21255
+ if (bits === undefined) {
21256
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
21257
+ }
21258
+ if (bits !== 2048) {
21259
+ throw new TFHECrsError({
21260
+ message: `Unsupported PublicParams bits format '${bits}'`,
21261
+ });
21262
+ }
21263
+ try {
21264
+ assertRecordStringProperty(params, 'publicParamsId', `arg`);
21265
+ assertUint8ArrayProperty(params, 'publicParams', `arg`);
21266
+ return TFHECrs._fromPublicParamsBytes({
21267
+ 2048: params,
21268
+ });
21269
+ }
21270
+ catch (e) {
21271
+ throw new TFHECrsError({
21272
+ message: 'Invalid public key (deserialization failed)',
21273
+ cause: e,
21274
+ });
21275
+ }
21276
+ }
21277
+ static fromPublicParamsBytesHex(params) {
21278
+ try {
21279
+ assertNonNullableRecordProperty(params, '2048', 'arg');
21280
+ assertRecordStringProperty(params['2048'], 'publicParamsId', `arg.2048`);
21281
+ assertRecordStringProperty(params['2048'], 'publicParams', `arg.2048`);
21282
+ return TFHECrs._fromPublicParamsBytes({
21283
+ 2048: {
21284
+ publicParams: hexToBytesFaster(params['2048'].publicParams, true /* strict */),
21285
+ publicParamsId: params['2048'].publicParamsId,
21286
+ },
21287
+ });
21288
+ }
21289
+ catch (e) {
21290
+ throw new TFHECrsError({
21291
+ message: 'Invalid public key (deserialization failed)',
20705
21292
  cause: e,
20706
21293
  });
20707
21294
  }
@@ -20719,7 +21306,8 @@ class TFHECrs {
20719
21306
  return TFHECrs._fromUrl(params);
20720
21307
  }
20721
21308
  catch (e) {
20722
- throw new Error('Impossible to fetch public key: wrong relayer url.', {
21309
+ throw new TFHECrsError({
21310
+ message: 'Impossible to fetch public key: wrong relayer url.',
20723
21311
  cause: e,
20724
21312
  });
20725
21313
  }
@@ -20750,6 +21338,22 @@ class TFHECrs {
20750
21338
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
20751
21339
  };
20752
21340
  }
21341
+ /*
21342
+ {
21343
+ id: string,
21344
+ bits: number,
21345
+ data: BytesHex,
21346
+ srcUrl?: string
21347
+ }
21348
+ */
21349
+ toBytesHex() {
21350
+ return {
21351
+ data: bytesToHexLarge(this._compactPkeCrs.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS)),
21352
+ id: this._id,
21353
+ bits: this._bits,
21354
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
21355
+ };
21356
+ }
20753
21357
  /*
20754
21358
  {
20755
21359
  2048: {
@@ -20758,9 +21362,11 @@ class TFHECrs {
20758
21362
  }
20759
21363
  }
20760
21364
  */
20761
- toPublicParamsWasm() {
21365
+ toPublicParams2048Wasm() {
20762
21366
  if (this._bits !== 2048) {
20763
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
21367
+ throw new TFHECrsError({
21368
+ message: `Unsupported PublicParams bits format '2048'`,
21369
+ });
20764
21370
  }
20765
21371
  const pp = {
20766
21372
  2048: {
@@ -20778,9 +21384,11 @@ class TFHECrs {
20778
21384
  }
20779
21385
  }
20780
21386
  */
20781
- toPublicParamsBytes() {
21387
+ toPublicParams2048Bytes() {
20782
21388
  if (this._bits !== 2048) {
20783
- throw new Error(`Unsupported PublicParams bits format ${this._bits}`);
21389
+ throw new TFHECrsError({
21390
+ message: `Unsupported PublicParams bits format '2048'`,
21391
+ });
20784
21392
  }
20785
21393
  const pp = {
20786
21394
  2048: {
@@ -20790,6 +21398,64 @@ class TFHECrs {
20790
21398
  };
20791
21399
  return pp;
20792
21400
  }
21401
+ /*
21402
+ {
21403
+ 2048: {
21404
+ publicParamsId: string,
21405
+ publicParams: BytesHex
21406
+ }
21407
+ }
21408
+ */
21409
+ toPublicParams2048BytesHex() {
21410
+ if (this._bits === undefined) {
21411
+ throw new TFHECrsError({ message: 'Missing PublicParams bits format' });
21412
+ }
21413
+ if (this._bits !== 2048) {
21414
+ throw new TFHECrsError({
21415
+ message: `Unsupported PublicParams bits format '${this._bits}'`,
21416
+ });
21417
+ }
21418
+ const pp = {
21419
+ 2048: {
21420
+ publicParams: this.toBytesHex().data,
21421
+ publicParamsId: this._id,
21422
+ },
21423
+ };
21424
+ return pp;
21425
+ }
21426
+ //////////////////////////////////////////////////////////////////////////////
21427
+ // JSON
21428
+ //////////////////////////////////////////////////////////////////////////////
21429
+ /*
21430
+ {
21431
+ __type: 'TFHECrs',
21432
+ id: string,
21433
+ data: BytesHex,
21434
+ srcUrl?: string
21435
+ }
21436
+ */
21437
+ toJSON() {
21438
+ return {
21439
+ __type: 'TFHECrs',
21440
+ ...this.toBytesHex(),
21441
+ };
21442
+ }
21443
+ static fromJSON(json) {
21444
+ if (json.__type !== 'TFHECrs') {
21445
+ throw new TFHECrsError({ message: 'Invalid TFHECrs JSON.' });
21446
+ }
21447
+ return TFHECrs.fromBytesHex(json);
21448
+ }
21449
+ }
21450
+
21451
+ class TFHEPublicKeyError extends RelayerErrorBase {
21452
+ constructor({ message, cause }) {
21453
+ super({
21454
+ message,
21455
+ name: 'TFHEPublicKeyError',
21456
+ ...(cause ? { cause: ensureError(cause) } : {}),
21457
+ });
21458
+ }
20793
21459
  }
20794
21460
 
20795
21461
  class TFHEPublicKey {
@@ -20801,6 +21467,12 @@ class TFHEPublicKey {
20801
21467
  this._tfheCompactPublicKey = params.tfheCompactPublicKey;
20802
21468
  this._srcUrl = params.srcUrl;
20803
21469
  }
21470
+ get id() {
21471
+ return this._id;
21472
+ }
21473
+ get srcUrl() {
21474
+ return this._srcUrl;
21475
+ }
20804
21476
  /*
20805
21477
  {
20806
21478
  id: string,
@@ -20885,6 +21557,30 @@ class TFHEPublicKey {
20885
21557
  });
20886
21558
  }
20887
21559
  }
21560
+ /*
21561
+ {
21562
+ id: string,
21563
+ data: BytesHex,
21564
+ srcUrl?: string
21565
+ }
21566
+ */
21567
+ static fromBytesHex(params) {
21568
+ let data;
21569
+ try {
21570
+ assertRecordStringProperty(params, 'data', 'arg');
21571
+ data = hexToBytesFaster(params.data, true /* strict */);
21572
+ }
21573
+ catch (e) {
21574
+ throw new Error('Invalid public key (deserialization failed)', {
21575
+ cause: e,
21576
+ });
21577
+ }
21578
+ return TFHEPublicKey.fromBytes({
21579
+ id: params?.id,
21580
+ srcUrl: params?.srcUrl,
21581
+ data,
21582
+ });
21583
+ }
20888
21584
  /*
20889
21585
  {
20890
21586
  id: string,
@@ -20945,6 +21641,20 @@ class TFHEPublicKey {
20945
21641
  ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
20946
21642
  };
20947
21643
  }
21644
+ /*
21645
+ {
21646
+ id: string,
21647
+ data: BytesHex,
21648
+ srcUrl?: string
21649
+ }
21650
+ */
21651
+ toBytesHex() {
21652
+ return {
21653
+ data: bytesToHexLarge(this._tfheCompactPublicKey.safe_serialize(SERIALIZED_SIZE_LIMIT_PK)),
21654
+ id: this._id,
21655
+ ...(this._srcUrl ? { srcUrl: this._srcUrl } : {}),
21656
+ };
21657
+ }
20948
21658
  /*
20949
21659
  {
20950
21660
  publicKey: TFHE.TfheCompactPublicKey
@@ -20969,6 +21679,75 @@ class TFHEPublicKey {
20969
21679
  publicKeyId: this._id,
20970
21680
  };
20971
21681
  }
21682
+ /*
21683
+ {
21684
+ publicKey: Uint8Array
21685
+ publicKeyId: string
21686
+ }
21687
+ */
21688
+ toPublicKeyBytesHex() {
21689
+ return {
21690
+ publicKey: this.toBytesHex().data,
21691
+ publicKeyId: this._id,
21692
+ };
21693
+ }
21694
+ static _fromPublicKeyBytes(params) {
21695
+ return TFHEPublicKey._fromBytes({
21696
+ data: params.publicKey,
21697
+ id: params.publicKeyId,
21698
+ srcUrl: params.srcUrl,
21699
+ });
21700
+ }
21701
+ static fromPublicKeyBytesHex(params) {
21702
+ try {
21703
+ assertRecordStringProperty(params, 'publicKey', `arg`);
21704
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
21705
+ return TFHEPublicKey._fromPublicKeyBytes({
21706
+ publicKey: hexToBytesFaster(params.publicKey, true /* strict */),
21707
+ publicKeyId: params.publicKeyId,
21708
+ });
21709
+ }
21710
+ catch (e) {
21711
+ throw new Error('Invalid public key (deserialization failed)', {
21712
+ cause: e,
21713
+ });
21714
+ }
21715
+ }
21716
+ static fromPublicKeyBytes(params) {
21717
+ try {
21718
+ assertUint8ArrayProperty(params, 'publicKey', `arg`);
21719
+ assertRecordStringProperty(params, 'publicKeyId', `arg`);
21720
+ return TFHEPublicKey._fromPublicKeyBytes(params);
21721
+ }
21722
+ catch (e) {
21723
+ throw new Error('Invalid public key (deserialization failed)', {
21724
+ cause: e,
21725
+ });
21726
+ }
21727
+ }
21728
+ //////////////////////////////////////////////////////////////////////////////
21729
+ // JSON
21730
+ //////////////////////////////////////////////////////////////////////////////
21731
+ /*
21732
+ {
21733
+ __type: 'TFHEPublicKey',
21734
+ id: string,
21735
+ data: BytesHex,
21736
+ srcUrl?: string
21737
+ }
21738
+ */
21739
+ toJSON() {
21740
+ return {
21741
+ __type: 'TFHEPublicKey',
21742
+ ...this.toBytesHex(),
21743
+ };
21744
+ }
21745
+ static fromJSON(json) {
21746
+ if (json.__type !== 'TFHEPublicKey') {
21747
+ throw new TFHEPublicKeyError({ message: 'Invalid TFHEPublicKey JSON.' });
21748
+ }
21749
+ return TFHEPublicKey.fromBytesHex(json);
21750
+ }
20972
21751
  }
20973
21752
 
20974
21753
  //const __KEY_URL_CACHE__: Record<string, RelayerV2PublicKey> = {};
@@ -21044,7 +21823,7 @@ class RelayerV2PublicKey {
21044
21823
  toBytes() {
21045
21824
  return {
21046
21825
  publicKey: this._publicKey.toBytes(),
21047
- publicParams: this._crs2048.toPublicParamsBytes(),
21826
+ publicParams: this._crs2048.toPublicParams2048Bytes(),
21048
21827
  };
21049
21828
  }
21050
21829
  }
@@ -21078,23 +21857,46 @@ class RelayerV2Fhevm extends AbstractRelayerFhevm {
21078
21857
  get relayerProvider() {
21079
21858
  return this._relayerProvider;
21080
21859
  }
21860
+ getPublicKeyInfo() {
21861
+ return {
21862
+ id: this._relayerPublicKey.getTFHEPublicKey().id,
21863
+ srcUrl: this._relayerPublicKey.getTFHEPublicKey().srcUrl,
21864
+ };
21865
+ }
21081
21866
  getPublicKeyBytes() {
21082
21867
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyBytes();
21083
21868
  }
21084
21869
  getPublicKeyWasm() {
21085
21870
  return this._relayerPublicKey.getTFHEPublicKey().toPublicKeyWasm();
21086
21871
  }
21087
- getPublicParamsBytes(bits) {
21872
+ getPublicParamsBytesForBits(bits) {
21873
+ if (bits === undefined) {
21874
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
21875
+ }
21088
21876
  if (bits !== 2048) {
21089
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
21877
+ throw new TFHECrsError({
21878
+ message: `Unsupported PublicParams bits format '${bits}'`,
21879
+ });
21090
21880
  }
21091
- return this._relayerPublicKey.getTFHECrs().toPublicParamsBytes()['2048'];
21881
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Bytes()['2048'];
21092
21882
  }
21093
- getPublicParamsWasm(bits) {
21883
+ getPublicParamsWasmForBits(bits) {
21884
+ if (bits === undefined) {
21885
+ throw new TFHECrsError({ message: `Missing PublicParams bits format` });
21886
+ }
21094
21887
  if (bits !== 2048) {
21095
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
21888
+ throw new TFHECrsError({
21889
+ message: `Unsupported PublicParams bits format '${bits}'`,
21890
+ });
21096
21891
  }
21097
- return this._relayerPublicKey.getTFHECrs().toPublicParamsWasm()['2048'];
21892
+ return this._relayerPublicKey.getTFHECrs().toPublicParams2048Wasm()['2048'];
21893
+ }
21894
+ getPublicParamsInfo() {
21895
+ return {
21896
+ id: this._relayerPublicKey.getTFHECrs().id,
21897
+ bits: this._relayerPublicKey.getTFHECrs().bits,
21898
+ srcUrl: this._relayerPublicKey.getTFHECrs().srcUrl,
21899
+ };
21098
21900
  }
21099
21901
  }
21100
21902
 
@@ -21133,24 +21935,42 @@ class RelayerV1Fhevm extends AbstractRelayerFhevm {
21133
21935
  publicKeyId: this._publicKeyData.publicKeyId,
21134
21936
  };
21135
21937
  }
21938
+ getPublicKeyInfo() {
21939
+ return {
21940
+ id: this._publicKeyData.publicKeyId,
21941
+ };
21942
+ }
21943
+ getPublicParamsInfo() {
21944
+ return {
21945
+ id: this._publicParamsData['2048'].publicParamsId,
21946
+ bits: 2048,
21947
+ };
21948
+ }
21136
21949
  getPublicKeyWasm() {
21137
21950
  return {
21138
21951
  publicKey: this._publicKeyData.publicKey,
21139
21952
  publicKeyId: this._publicKeyData.publicKeyId,
21140
21953
  };
21141
21954
  }
21142
- getPublicParamsBytes(bits) {
21955
+ getPublicParamsBytesForBits(bits) {
21956
+ if (bits === undefined) {
21957
+ throw new Error(`Missing PublicParams bits format`);
21958
+ }
21143
21959
  if (bits !== 2048) {
21144
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
21960
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
21145
21961
  }
21146
- return {
21962
+ const res = {
21147
21963
  publicParams: this._publicParamsData['2048'].publicParams.safe_serialize(SERIALIZED_SIZE_LIMIT_CRS),
21148
21964
  publicParamsId: this._publicParamsData['2048'].publicParamsId,
21149
21965
  };
21966
+ return res;
21150
21967
  }
21151
- getPublicParamsWasm(bits) {
21968
+ getPublicParamsWasmForBits(bits) {
21969
+ if (bits === undefined) {
21970
+ throw new Error(`Missing PublicParams bits format`);
21971
+ }
21152
21972
  if (bits !== 2048) {
21153
- throw new Error(`Unsupported PublicParams bits format ${bits}`);
21973
+ throw new Error(`Unsupported PublicParams bits format '${bits}'`);
21154
21974
  }
21155
21975
  return {
21156
21976
  publicParams: this._publicParamsData['2048'].publicParams,
@@ -21171,11 +21991,16 @@ async function createRelayerFhevm(config) {
21171
21991
  publicParams: config.publicParams,
21172
21992
  });
21173
21993
  }
21174
- return RelayerV1Fhevm.fromConfig({
21175
- relayerVersionUrl: resolved.url,
21176
- publicKey: config.publicKey,
21177
- publicParams: config.publicParams,
21178
- });
21994
+ else if (resolved.version === 1) {
21995
+ return RelayerV1Fhevm.fromConfig({
21996
+ relayerVersionUrl: resolved.url,
21997
+ publicKey: config.publicKey,
21998
+ publicParams: config.publicParams,
21999
+ });
22000
+ }
22001
+ else {
22002
+ throw new Error(`Invalid relayerUrl: ${config.relayerUrl}`);
22003
+ }
21179
22004
  }
21180
22005
  function _resolveRelayerUrl(value, defaultVersion) {
21181
22006
  if (!value || typeof value !== 'string') {
@@ -21275,7 +22100,28 @@ const createInstance = async (config) => {
21275
22100
  const coprocessorSigners = await getCoprocessorSigners(provider, inputVerifierContractAddress);
21276
22101
  const thresholdCoprocessorSigners = await getCoprocessorSignersThreshold(provider, inputVerifierContractAddress);
21277
22102
  return {
21278
- createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerFhevm.relayerProvider, relayerFhevm.getPublicKeyWasm().publicKey, { 2048: relayerFhevm.getPublicParamsWasm(2048) }, coprocessorSigners, thresholdCoprocessorSigners, auth && { auth }),
22103
+ createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, relayerFhevm.relayerProvider, relayerFhevm.getPublicKeyWasm().publicKey, { 2048: relayerFhevm.getPublicParamsWasmForBits(2048) }, coprocessorSigners, thresholdCoprocessorSigners, auth && { auth }),
22104
+ requestZKProofVerification: (zkProof, options) => {
22105
+ if (zkProof.chainId !== chainId ||
22106
+ zkProof.aclContractAddress !== aclContractAddress) {
22107
+ throw new Error('Invalid ZKProof');
22108
+ }
22109
+ return requestCiphertextWithZKProofVerification({
22110
+ ciphertext: zkProof.ciphertextWithZkProof,
22111
+ aclContractAddress: aclContractAddress,
22112
+ contractAddress: zkProof.contractAddress,
22113
+ userAddress: zkProof.userAddress,
22114
+ chainId,
22115
+ gatewayChainId,
22116
+ bits: zkProof.bits,
22117
+ coprocessorSigners,
22118
+ extraData: '0x00',
22119
+ thresholdCoprocessorSigners,
22120
+ relayerProvider: relayerFhevm.relayerProvider,
22121
+ verifyingContractAddressInputVerification: verifyingContractAddressInputVerification,
22122
+ options,
22123
+ });
22124
+ },
21279
22125
  generateKeypair,
21280
22126
  createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
21281
22127
  publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress,
@@ -21285,7 +22131,7 @@ const createInstance = async (config) => {
21285
22131
  //cleanURL(config.relayerUrl),
21286
22132
  relayerFhevm.relayerProvider, provider, auth && { auth }),
21287
22133
  getPublicKey: () => relayerFhevm.getPublicKeyBytes(),
21288
- getPublicParams: (bits) => relayerFhevm.getPublicParamsBytes(bits),
22134
+ getPublicParams: (bits) => relayerFhevm.getPublicParamsBytesForBits(bits),
21289
22135
  // getPublicKey: () =>
21290
22136
  // publicKeyData.publicKey
21291
22137
  // ? {