@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/bin/commands/config.js +13 -0
- package/bin/commands/handle.js +22 -0
- package/bin/commands/input-proof.js +75 -0
- package/bin/commands/pubkey-clear.js +18 -0
- package/bin/commands/pubkey-fetch.js +9 -0
- package/bin/commands/pubkey-info.js +44 -0
- package/bin/commands/public-decrypt.js +64 -0
- package/bin/commands/test-fhecounter-getcount.js +49 -0
- package/bin/commands/zkproof-generate.js +68 -0
- package/bin/instance.js +15 -0
- package/bin/pubkeyCache.js +126 -0
- package/bin/relayer.js +132 -59
- package/bin/utils.js +345 -8
- package/bundle/relayer-sdk-js.js +5902 -5206
- package/bundle/relayer-sdk-js.umd.cjs +5 -5
- package/lib/internal.js +6138 -0
- package/lib/node.cjs +1061 -215
- package/lib/node.d.ts +8 -1
- package/lib/node.js +1061 -215
- package/lib/web.d.ts +8 -1
- package/lib/web.js +1060 -214
- package/package.json +1 -1
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.
|
|
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
|
-
?
|
|
17604
|
-
:
|
|
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
|
|
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
|
|
17869
|
-
if (!
|
|
17870
|
-
throw new InvalidTypeError({ expectedType: '
|
|
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.
|
|
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 ??
|
|
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
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
|
|
17994
|
-
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
|
|
17998
|
-
|
|
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
|
|
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) =>
|
|
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(
|
|
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 =
|
|
18518
|
+
const chainIdBytes32 = numberToBytes32(chainId);
|
|
18133
18519
|
const encoder = new TextEncoder();
|
|
18134
18520
|
const domainSepBytes = encoder.encode(FhevmHandle.HANDLE_HASH_DOMAIN_SEPARATOR);
|
|
18135
|
-
|
|
18136
|
-
|
|
18137
|
-
|
|
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
|
-
|
|
18280
|
-
return
|
|
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:
|
|
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 =
|
|
18319
|
-
let current =
|
|
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 =
|
|
18784
|
+
let inputProof = numberToHexNo0x(handles.length);
|
|
18359
18785
|
const numSigners = signatures.length;
|
|
18360
|
-
inputProof +=
|
|
18361
|
-
const listHandlesStr = handles.map((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.
|
|
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
|
|
18903
|
+
let fheTypeIdList = [];
|
|
18478
18904
|
for (const handle of handles) {
|
|
18479
|
-
const typeDiscriminant = FhevmHandle.
|
|
18480
|
-
|
|
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 =
|
|
18488
|
-
const abiType =
|
|
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 +
|
|
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
|
-
?
|
|
18507
|
-
:
|
|
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:
|
|
18666
|
-
privateKey:
|
|
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
|
-
|
|
19792
|
+
_fhevmAuth;
|
|
19346
19793
|
_retryAfterTimeoutPromiseFuncReject;
|
|
19347
19794
|
_onProgress;
|
|
19348
|
-
|
|
19795
|
+
_requestMaxDurationInMs;
|
|
19349
19796
|
_requestStartTimestamp;
|
|
19350
19797
|
_requestGlobalTimeoutID;
|
|
19351
19798
|
_throwErrorIfNoRetryAfter;
|
|
19352
|
-
static
|
|
19353
|
-
static
|
|
19354
|
-
static
|
|
19355
|
-
static
|
|
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.
|
|
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.
|
|
19396
|
-
params.
|
|
19397
|
-
RelayerV2AsyncRequest.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
20061
|
+
retryAfterMs,
|
|
19601
20062
|
elapsed,
|
|
19602
20063
|
});
|
|
19603
|
-
|
|
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
|
-
|
|
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
|
-
|
|
20117
|
+
retryAfterMs,
|
|
19660
20118
|
retryCount: this._retryCount,
|
|
19661
20119
|
elapsed,
|
|
19662
|
-
|
|
20120
|
+
relayerApiError: bodyJson.error,
|
|
19663
20121
|
});
|
|
19664
20122
|
// Wait if needed (minimum 1s)
|
|
19665
|
-
await this._setRetryAfterTimeout(
|
|
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
|
-
|
|
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
|
-
|
|
20325
|
+
retryAfterMs,
|
|
19868
20326
|
retryCount: this._retryCount,
|
|
19869
20327
|
elapsed,
|
|
19870
20328
|
});
|
|
19871
20329
|
// Wait if needed (minimum 1s)
|
|
19872
|
-
await this._setRetryAfterTimeout(
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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',
|
|
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.
|
|
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.
|
|
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 >=
|
|
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
|
|
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.
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
21365
|
+
toPublicParams2048Wasm() {
|
|
20762
21366
|
if (this._bits !== 2048) {
|
|
20763
|
-
throw new
|
|
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
|
-
|
|
21387
|
+
toPublicParams2048Bytes() {
|
|
20782
21388
|
if (this._bits !== 2048) {
|
|
20783
|
-
throw new
|
|
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.
|
|
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
|
-
|
|
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
|
|
21877
|
+
throw new TFHECrsError({
|
|
21878
|
+
message: `Unsupported PublicParams bits format '${bits}'`,
|
|
21879
|
+
});
|
|
21090
21880
|
}
|
|
21091
|
-
return this._relayerPublicKey.getTFHECrs().
|
|
21881
|
+
return this._relayerPublicKey.getTFHECrs().toPublicParams2048Bytes()['2048'];
|
|
21092
21882
|
}
|
|
21093
|
-
|
|
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
|
|
21888
|
+
throw new TFHECrsError({
|
|
21889
|
+
message: `Unsupported PublicParams bits format '${bits}'`,
|
|
21890
|
+
});
|
|
21096
21891
|
}
|
|
21097
|
-
return this._relayerPublicKey.getTFHECrs().
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
21175
|
-
|
|
21176
|
-
|
|
21177
|
-
|
|
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.
|
|
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.
|
|
22134
|
+
getPublicParams: (bits) => relayerFhevm.getPublicParamsBytesForBits(bits),
|
|
21289
22135
|
// getPublicKey: () =>
|
|
21290
22136
|
// publicKeyData.publicKey
|
|
21291
22137
|
// ? {
|