@zama-fhe/relayer-sdk 0.3.0-3 → 0.3.0-5

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
@@ -16282,6 +16282,9 @@ const bytesToBigInt = function (byteArray) {
16282
16282
  .join('');
16283
16283
  return BigInt(`0x${hex}`);
16284
16284
  };
16285
+ function ensure0x(s) {
16286
+ return !s.startsWith('0x') ? `0x${s}` : s;
16287
+ }
16285
16288
 
16286
16289
  function setAuth(init, auth) {
16287
16290
  if (auth) {
@@ -16788,6 +16791,17 @@ const NumEncryptedBits = {
16788
16791
  7: 160, // eaddress
16789
16792
  8: 256, // euint256
16790
16793
  };
16794
+ function getHandleType(handle) {
16795
+ if (handle.length !== 66) {
16796
+ throw new Error(`Handle ${handle} is not of valid length`);
16797
+ }
16798
+ const hexPair = handle.slice(-4, -2).toLowerCase();
16799
+ const typeDiscriminant = parseInt(hexPair, 16);
16800
+ if (!(typeDiscriminant in NumEncryptedBits)) {
16801
+ throw new Error(`Handle ${handle} is not of valid type`);
16802
+ }
16803
+ return typeDiscriminant;
16804
+ }
16791
16805
  function checkEncryptedBits(handles) {
16792
16806
  let total = 0;
16793
16807
  for (const handle of handles) {
@@ -16816,37 +16830,30 @@ const aclABI$1 = [
16816
16830
  ];
16817
16831
  const MAX_USER_DECRYPT_CONTRACT_ADDRESSES = 10;
16818
16832
  const MAX_USER_DECRYPT_DURATION_DAYS = BigInt(365);
16819
- function formatAccordingToType(decryptedBigInt, type) {
16833
+ function formatAccordingToType(clearValueAsBigInt, type) {
16820
16834
  if (type === 0) {
16821
16835
  // ebool
16822
- return decryptedBigInt === BigInt(1);
16836
+ return clearValueAsBigInt === BigInt(1);
16823
16837
  }
16824
16838
  else if (type === 7) {
16825
16839
  // eaddress
16826
- return getAddress$1('0x' + decryptedBigInt.toString(16).padStart(40, '0'));
16827
- }
16828
- else if (type === 9) {
16829
- // ebytes64
16830
- return '0x' + decryptedBigInt.toString(16).padStart(128, '0');
16840
+ return getAddress$1('0x' + clearValueAsBigInt.toString(16).padStart(40, '0'));
16831
16841
  }
16832
- else if (type === 10) {
16833
- // ebytes128
16834
- return '0x' + decryptedBigInt.toString(16).padStart(256, '0');
16842
+ else if (type > 8 || type == 1) {
16843
+ // type == 1 : euint4 (not supported)
16844
+ throw new Error(`Unsupported handle type ${type}`);
16835
16845
  }
16836
- else if (type === 11) {
16837
- // ebytes256
16838
- return '0x' + decryptedBigInt.toString(16).padStart(512, '0');
16839
- } // euintXXX
16840
- return decryptedBigInt;
16846
+ // euintXXX
16847
+ return clearValueAsBigInt;
16841
16848
  }
16842
- function buildUserDecryptedResult(handles, listBigIntDecryptions) {
16849
+ function buildUserDecryptResults(handles, listBigIntDecryptions) {
16843
16850
  let typesList = [];
16844
16851
  for (const handle of handles) {
16845
16852
  const hexPair = handle.slice(-4, -2).toLowerCase();
16846
16853
  const typeDiscriminant = parseInt(hexPair, 16);
16847
16854
  typesList.push(typeDiscriminant);
16848
16855
  }
16849
- let results = {};
16856
+ const results = {};
16850
16857
  handles.forEach((handle, idx) => (results[handle] = formatAccordingToType(listBigIntDecryptions[idx], typesList[idx])));
16851
16858
  return results;
16852
16859
  }
@@ -16952,7 +16959,7 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
16952
16959
  };
16953
16960
  const decryption = TKMS.process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json.response, pubKey, privKey, true);
16954
16961
  const listBigIntDecryptions = decryption.map((d) => bytesToBigInt(d.bytes));
16955
- const results = buildUserDecryptedResult(handles.map((h) => h.handle), listBigIntDecryptions);
16962
+ const results = buildUserDecryptResults(handles.map((h) => h.handle), listBigIntDecryptions);
16956
16963
  return results;
16957
16964
  }
16958
16965
  catch (e) {
@@ -17007,7 +17014,7 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
17007
17014
  checkEncryptedValue(Number(value), 1);
17008
17015
  checkLimit(2);
17009
17016
  builder.push_boolean(!!value);
17010
- bits.push(1); // ebool takes 2 encrypted bits
17017
+ bits.push(2); // ebool takes 2 encrypted bits
17011
17018
  return this;
17012
17019
  },
17013
17020
  add8(value) {
@@ -17061,36 +17068,6 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
17061
17068
  bits.push(256);
17062
17069
  return this;
17063
17070
  },
17064
- addBytes64(value) {
17065
- if (value.length !== 64)
17066
- throw Error('Uncorrect length of input Uint8Array, should be 64 for an ebytes64');
17067
- const bigIntValue = bytesToBigInt(value);
17068
- checkEncryptedValue(bigIntValue, 512);
17069
- checkLimit(512);
17070
- builder.push_u512(bigIntValue);
17071
- bits.push(512);
17072
- return this;
17073
- },
17074
- addBytes128(value) {
17075
- if (value.length !== 128)
17076
- throw Error('Uncorrect length of input Uint8Array, should be 128 for an ebytes128');
17077
- const bigIntValue = bytesToBigInt(value);
17078
- checkEncryptedValue(bigIntValue, 1024);
17079
- checkLimit(1024);
17080
- builder.push_u1024(bigIntValue);
17081
- bits.push(1024);
17082
- return this;
17083
- },
17084
- addBytes256(value) {
17085
- if (value.length !== 256)
17086
- throw Error('Uncorrect length of input Uint8Array, should be 256 for an ebytes256');
17087
- const bigIntValue = bytesToBigInt(value);
17088
- checkEncryptedValue(bigIntValue, 2048);
17089
- checkLimit(2048);
17090
- builder.push_u2048(bigIntValue);
17091
- bits.push(2048);
17092
- return this;
17093
- },
17094
17071
  getBits() {
17095
17072
  return bits;
17096
17073
  },
@@ -17123,18 +17100,37 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
17123
17100
  };
17124
17101
  };
17125
17102
 
17103
+ /**
17104
+ * **FHE Type Mapping for Input Builders**
17105
+ * * Maps the **number of encrypted bits** used by a FHEVM primary type
17106
+ * to its corresponding **FheTypeId**. This constant is primarily used by
17107
+ * `EncryptedInput` and `RelayerEncryptedInput` builders to determine the correct
17108
+ * input type and calculate the total required bit-length.
17109
+ *
17110
+ * **Structure: \{ Encrypted Bit Length: FheTypeId \}**
17111
+ *
17112
+ * | Bits | FheTypeId | FHE Type Name | Note |
17113
+ * | :--- | :-------- | :------------ | :--- |
17114
+ * | 2 | 0 | `ebool` | The boolean type. |
17115
+ * | (N/A)| 1 | `euint4` | **Deprecated** and omitted from this map. |
17116
+ * | 8 | 2 | `euint8` | |
17117
+ * | 16 | 3 | `euint16` | |
17118
+ * | 32 | 4 | `euint32` | |
17119
+ * | 64 | 5 | `euint64` | |
17120
+ * | 128 | 6 | `euint128` | |
17121
+ * | 160 | 7 | `eaddress` | Used for encrypted Ethereum addresses. |
17122
+ * | 256 | 8 | `euint256` | The maximum supported integer size. |
17123
+ */
17126
17124
  const ENCRYPTION_TYPES = {
17127
- 1: 0, // ebool takes 2 encrypted bits
17128
- 8: 2,
17129
- 16: 3,
17130
- 32: 4,
17131
- 64: 5,
17132
- 128: 6,
17133
- 160: 7,
17134
- 256: 8,
17135
- 512: 9,
17136
- 1024: 10,
17137
- 2048: 11,
17125
+ 2: 0, // ebool (FheTypeId=0) is using 2 encrypted bits
17126
+ // euint4 (FheTypeId=1) is deprecated
17127
+ 8: 2, // euint8 (FheTypeId=2) is using 8 encrypted bits
17128
+ 16: 3, // euint16 (FheTypeId=3) is using 16 encrypted bits
17129
+ 32: 4, // euint32 (FheTypeId=4) is using 32 encrypted bits
17130
+ 64: 5, // euint64 (FheTypeId=5) is using 64 encrypted bits
17131
+ 128: 6, // euint128 (FheTypeId=128) is using 128 encrypted bits
17132
+ 160: 7, // eaddress (FheTypeId=7) is using 160 encrypted bits
17133
+ 256: 8, // euint256 (FheTypeId=8) is using 256 encrypted bits
17138
17134
  };
17139
17135
 
17140
17136
  const MAX_UINT64 = BigInt('18446744073709551615'); // 2^64 - 1
@@ -17363,6 +17359,74 @@ function isThresholdReached(kmsSigners, recoveredAddresses, threshold) {
17363
17359
  }
17364
17360
  return recoveredAddresses.length >= threshold;
17365
17361
  }
17362
+ function abiEncodeClearValues(clearValues) {
17363
+ const handlesBytes32Hex = Object.keys(clearValues);
17364
+ const abiTypes = [];
17365
+ const abiValues = [];
17366
+ for (let i = 0; i < handlesBytes32Hex.length; ++i) {
17367
+ const handle = handlesBytes32Hex[i];
17368
+ const handleType = getHandleType(handle);
17369
+ let clearTextValue = clearValues[handle];
17370
+ if (typeof clearTextValue === 'boolean') {
17371
+ clearTextValue = clearTextValue ? '0x01' : '0x00';
17372
+ }
17373
+ const clearTextValueBigInt = BigInt(clearTextValue);
17374
+ //abiTypes.push(fhevmTypeInfo.solidityTypeName);
17375
+ abiTypes.push('uint256');
17376
+ switch (handleType) {
17377
+ // eaddress
17378
+ case 7: {
17379
+ // string
17380
+ abiValues.push(`0x${clearTextValueBigInt.toString(16).padStart(40, '0')}`);
17381
+ break;
17382
+ }
17383
+ // ebool
17384
+ case 0: {
17385
+ // bigint (0 or 1)
17386
+ if (clearTextValueBigInt !== BigInt(0) &&
17387
+ clearTextValueBigInt !== BigInt(1)) {
17388
+ throw new Error(`Invalid ebool clear text value ${clearTextValueBigInt}. Expecting 0 or 1.`);
17389
+ }
17390
+ abiValues.push(clearTextValueBigInt);
17391
+ break;
17392
+ }
17393
+ case 2: //euint8
17394
+ case 3: //euint16
17395
+ case 4: //euint32
17396
+ case 5: //euint64
17397
+ case 6: //euint128
17398
+ case 7: {
17399
+ //euint256
17400
+ // bigint
17401
+ abiValues.push(clearTextValueBigInt);
17402
+ break;
17403
+ }
17404
+ default: {
17405
+ throw new Error(`Unsupported Fhevm primitive type id: ${handleType}`);
17406
+ }
17407
+ }
17408
+ }
17409
+ const abiCoder = ethers.AbiCoder.defaultAbiCoder();
17410
+ // ABI encode the decryptedResult as done in the KMS, since all decrypted values
17411
+ // are native static types, thay have same abi-encoding as uint256:
17412
+ const abiEncodedClearValues = abiCoder.encode(abiTypes, abiValues);
17413
+ return {
17414
+ abiTypes,
17415
+ abiValues,
17416
+ abiEncodedClearValues,
17417
+ };
17418
+ }
17419
+ function buildDecryptionProof(kmsSignatures, extraData) {
17420
+ // Build the decryptionProof as numSigners + KMS signatures + extraData
17421
+ const packedNumSigners = ethers.solidityPacked(['uint8'], [kmsSignatures.length]);
17422
+ const packedSignatures = ethers.solidityPacked(Array(kmsSignatures.length).fill('bytes'), kmsSignatures);
17423
+ const decryptionProof = ethers.concat([
17424
+ packedNumSigners,
17425
+ packedSignatures,
17426
+ extraData,
17427
+ ]);
17428
+ return decryptionProof;
17429
+ }
17366
17430
  const CiphertextType = {
17367
17431
  0: 'bool',
17368
17432
  2: 'uint256',
@@ -17373,7 +17437,7 @@ const CiphertextType = {
17373
17437
  7: 'address',
17374
17438
  8: 'uint256',
17375
17439
  };
17376
- function deserializeDecryptedResult(handles, decryptedResult) {
17440
+ function deserializeClearValues(handles, decryptedResult) {
17377
17441
  let typesList = [];
17378
17442
  for (const handle of handles) {
17379
17443
  const hexPair = handle.slice(-4, -2).toLowerCase();
@@ -17392,7 +17456,7 @@ function deserializeDecryptedResult(handles, decryptedResult) {
17392
17456
  const decoded = coder.decode(['uint256', ...abiTypes, 'bytes[]'], restoredEncoded);
17393
17457
  // strip dummy first/last element
17394
17458
  const rawValues = decoded.slice(1, 1 + typesList.length);
17395
- let results = {};
17459
+ const results = {};
17396
17460
  handles.forEach((handle, idx) => (results[handle] = rawValues[idx]));
17397
17461
  return results;
17398
17462
  }
@@ -17437,22 +17501,26 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
17437
17501
  ],
17438
17502
  };
17439
17503
  const result = json.response[0];
17440
- const decryptedResult = result.decrypted_value.startsWith('0x')
17441
- ? result.decrypted_value
17442
- : `0x${result.decrypted_value}`;
17443
- const signatures = result.signatures;
17504
+ const decryptedResult = ensure0x(result.decrypted_value);
17505
+ const kmsSignatures = result.signatures.map(ensure0x);
17506
+ // TODO result.extra_data (RelayerPublicDecryptJsonResponse)
17444
17507
  const signedExtraData = '0x';
17445
- const recoveredAddresses = signatures.map((signature) => {
17446
- const sig = signature.startsWith('0x') ? signature : `0x${signature}`;
17447
- const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData: signedExtraData }, sig);
17508
+ const recoveredAddresses = kmsSignatures.map((kmsSignature) => {
17509
+ const recoveredAddress = ethers.verifyTypedData(domain, types, { ctHandles: handles, decryptedResult, extraData: signedExtraData }, kmsSignature);
17448
17510
  return recoveredAddress;
17449
17511
  });
17450
17512
  const thresholdReached = isThresholdReached(kmsSigners, recoveredAddresses, thresholdSigners);
17451
17513
  if (!thresholdReached) {
17452
17514
  throw Error('KMS signers threshold is not reached');
17453
17515
  }
17454
- const results = deserializeDecryptedResult(handles, decryptedResult);
17455
- return results;
17516
+ const clearValues = deserializeClearValues(handles, decryptedResult);
17517
+ const abiEnc = abiEncodeClearValues(clearValues);
17518
+ const decryptionProof = buildDecryptionProof(kmsSignatures, signedExtraData);
17519
+ return {
17520
+ clearValues,
17521
+ abiEncodedClearValues: abiEnc.abiEncodedClearValues,
17522
+ decryptionProof,
17523
+ };
17456
17524
  };
17457
17525
 
17458
17526
  /**
@@ -17562,23 +17630,23 @@ const generateKeypair = () => {
17562
17630
  global.fetch = fetchRetry(global.fetch, { retries: 5, retryDelay: 500 });
17563
17631
  const SepoliaConfig = {
17564
17632
  // ACL_CONTRACT_ADDRESS (FHEVM Host chain)
17565
- aclContractAddress: '0x687820221192C5B662b25367F70076A37bc79b6c',
17633
+ aclContractAddress: '0xf0Ffdc93b7E186bC2f8CB3dAA75D86d1930A433D',
17566
17634
  // KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
17567
- kmsContractAddress: '0x1364cBBf2cDF5032C47d8226a6f6FBD2AFCDacAC',
17635
+ kmsContractAddress: '0xbE0E383937d564D7FF0BC3b46c51f0bF8d5C311A',
17568
17636
  // INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
17569
- inputVerifierContractAddress: '0xbc91f3daD1A5F19F8390c400196e58073B6a0BC4',
17637
+ inputVerifierContractAddress: '0xBBC1fFCdc7C316aAAd72E807D9b0272BE8F84DA0',
17570
17638
  // DECRYPTION_ADDRESS (Gateway chain)
17571
- verifyingContractAddressDecryption: '0xb6E160B1ff80D67Bfe90A85eE06Ce0A2613607D1',
17639
+ verifyingContractAddressDecryption: '0x5D8BD78e2ea6bbE41f26dFe9fdaEAa349e077478',
17572
17640
  // INPUT_VERIFICATION_ADDRESS (Gateway chain)
17573
- verifyingContractAddressInputVerification: '0x7048C39f048125eDa9d678AEbaDfB22F7900a29F',
17641
+ verifyingContractAddressInputVerification: '0x483b9dE06E4E4C7D35CCf5837A1668487406D955',
17574
17642
  // FHEVM Host chain id
17575
17643
  chainId: 11155111,
17576
17644
  // Gateway chain id
17577
- gatewayChainId: 55815,
17645
+ gatewayChainId: 10901,
17578
17646
  // Optional RPC provider to host chain
17579
- network: 'https://eth-sepolia.public.blastapi.io',
17647
+ network: 'https://ethereum-sepolia-rpc.publicnode.com',
17580
17648
  // Relayer URL
17581
- relayerUrl: 'https://relayer.testnet.zama.cloud',
17649
+ relayerUrl: 'https://relayer.testnet.zama.org',
17582
17650
  };
17583
17651
  const createInstance = async (config) => {
17584
17652
  const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, auth, } = config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zama-fhe/relayer-sdk",
3
- "version": "0.3.0-3",
3
+ "version": "0.3.0-5",
4
4
  "description": "fhevm Relayer SDK",
5
5
  "main": "lib/node.js",
6
6
  "types": "lib/node.d.ts",
@@ -11,19 +11,19 @@
11
11
  },
12
12
  "exports": {
13
13
  "./web": {
14
+ "types": "./lib/web.d.ts",
14
15
  "import": "./lib/web.js",
15
- "require": "./lib/web.js",
16
- "types": "./lib/web.d.ts"
16
+ "require": "./lib/web.js"
17
17
  },
18
18
  "./bundle": {
19
+ "types": "./bundle.d.ts",
19
20
  "import": "./bundle.js",
20
- "require": "./bundle.js",
21
- "types": "./bundle.d.ts"
21
+ "require": "./bundle.js"
22
22
  },
23
23
  "./node": {
24
+ "types": "./lib/node.d.ts",
24
25
  "import": "./lib/node.js",
25
- "require": "./lib/node.cjs",
26
- "types": "./lib/node.d.ts"
26
+ "require": "./lib/node.cjs"
27
27
  },
28
28
  "./package.json": "./package.json"
29
29
  },