@zama-fhe/relayer-sdk 0.1.0-5 → 0.1.0-7
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/bundle/fhevm.js +5549 -5515
- package/bundle/fhevm.umd.cjs +12 -12
- package/bundle/tfhe_bg.wasm +0 -0
- package/bundle/workerHelpers.js +1 -1
- package/bundle.d.ts +1 -0
- package/bundle.js +3 -12
- package/lib/node.cjs +85 -32
- package/lib/node.d.ts +4 -2
- package/lib/node.js +60 -27
- package/lib/tfhe_bg.wasm +0 -0
- package/lib/web.d.ts +4 -3
- package/lib/web.js +304 -269
- package/lib/workerHelpers.js +16 -15
- package/package.json +9 -6
package/bundle.d.ts
CHANGED
package/bundle.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (window && window.fhevm) {
|
|
5
|
-
return window.fhevm[functionName](...params);
|
|
6
|
-
}
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const initFhevm = waitForFunction('initFhevm');
|
|
10
|
-
const createInstance = waitForFunction('createInstance');
|
|
11
|
-
|
|
12
|
-
export { initFhevm, createInstance };
|
|
1
|
+
export const initFhevm = window.fhevm.initFhevm;
|
|
2
|
+
export const createInstance = window.fhevm.createInstance;
|
|
3
|
+
export const SepoliaConfig = window.fhevm.SepoliaConfig;
|
package/lib/node.cjs
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var TFHEPkg = require('node-tfhe');
|
|
4
|
+
var TKMSPkg = require('node-tkms');
|
|
3
5
|
var ethers = require('ethers');
|
|
4
|
-
var nodeTfhe = require('node-tfhe');
|
|
5
|
-
var nodeTkms = require('node-tkms');
|
|
6
6
|
var createHash = require('keccak');
|
|
7
7
|
var fetchRetry = require('fetch-retry');
|
|
8
8
|
|
|
9
|
+
function _interopNamespaceDefault(e) {
|
|
10
|
+
var n = Object.create(null);
|
|
11
|
+
if (e) {
|
|
12
|
+
Object.keys(e).forEach(function (k) {
|
|
13
|
+
if (k !== 'default') {
|
|
14
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
15
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return e[k]; }
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
n.default = e;
|
|
23
|
+
return Object.freeze(n);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var TFHEPkg__namespace = /*#__PURE__*/_interopNamespaceDefault(TFHEPkg);
|
|
27
|
+
var TKMSPkg__namespace = /*#__PURE__*/_interopNamespaceDefault(TKMSPkg);
|
|
28
|
+
|
|
9
29
|
const SERIALIZED_SIZE_LIMIT_CIPHERTEXT = BigInt(1024 * 1024 * 512);
|
|
10
30
|
const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
|
|
11
31
|
const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
|
|
@@ -82,10 +102,17 @@ const getKeysFromRelayer = async (url, publicKeyId) => {
|
|
|
82
102
|
if (!publicParams2048Response.ok) {
|
|
83
103
|
throw new Error(`HTTP error! status: ${publicParams2048Response.status} on ${publicParams2048Response.url}`);
|
|
84
104
|
}
|
|
85
|
-
|
|
105
|
+
let publicParams2048;
|
|
106
|
+
if (typeof publicParams2048Response.bytes === 'function') {
|
|
107
|
+
// bytes is not widely supported yet
|
|
108
|
+
publicParams2048 = await publicParams2048Response.bytes();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
publicParams2048 = new Uint8Array(await publicParams2048Response.arrayBuffer());
|
|
112
|
+
}
|
|
86
113
|
let pub_key;
|
|
87
114
|
try {
|
|
88
|
-
pub_key =
|
|
115
|
+
pub_key = TFHE.TfheCompactPublicKey.safe_deserialize(publicKey, SERIALIZED_SIZE_LIMIT_PK);
|
|
89
116
|
}
|
|
90
117
|
catch (e) {
|
|
91
118
|
throw new Error('Invalid public key (deserialization failed)', {
|
|
@@ -94,7 +121,7 @@ const getKeysFromRelayer = async (url, publicKeyId) => {
|
|
|
94
121
|
}
|
|
95
122
|
let crs;
|
|
96
123
|
try {
|
|
97
|
-
crs =
|
|
124
|
+
crs = TFHE.CompactPkeCrs.safe_deserialize(new Uint8Array(publicParams2048), SERIALIZED_SIZE_LIMIT_CRS);
|
|
98
125
|
}
|
|
99
126
|
catch (e) {
|
|
100
127
|
throw new Error('Invalid crs (deserialization failed)', {
|
|
@@ -163,7 +190,7 @@ const getTfheCompactPublicKey = async (config) => {
|
|
|
163
190
|
const buff = config.publicKey.data;
|
|
164
191
|
try {
|
|
165
192
|
return {
|
|
166
|
-
publicKey:
|
|
193
|
+
publicKey: TFHE.TfheCompactPublicKey.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_PK),
|
|
167
194
|
publicKeyId: config.publicKey.id,
|
|
168
195
|
};
|
|
169
196
|
}
|
|
@@ -187,7 +214,7 @@ const getPublicParams = async (config) => {
|
|
|
187
214
|
try {
|
|
188
215
|
return {
|
|
189
216
|
2048: {
|
|
190
|
-
publicParams:
|
|
217
|
+
publicParams: TFHE.CompactPkeCrs.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_CRS),
|
|
191
218
|
publicParamsId: config.publicParams['2048'].publicParamsId,
|
|
192
219
|
},
|
|
193
220
|
};
|
|
@@ -314,6 +341,8 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
|
|
|
314
341
|
}
|
|
315
342
|
const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
|
|
316
343
|
// Casting handles if string
|
|
344
|
+
const signatureSanitized = signature.replace(/^(0x)/, '');
|
|
345
|
+
const publicKeySanitized = publicKey.replace(/^(0x)/, '');
|
|
317
346
|
const handles = _handles.map((h) => ({
|
|
318
347
|
handle: typeof h.handle === 'string'
|
|
319
348
|
? toHexString(fromHexString(h.handle), true)
|
|
@@ -355,8 +384,8 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
355
384
|
contractsChainId: chainId.toString(), // Convert to string
|
|
356
385
|
contractAddresses: contractAddresses.map((c) => ethers.getAddress(c)),
|
|
357
386
|
userAddress: ethers.getAddress(userAddress),
|
|
358
|
-
signature:
|
|
359
|
-
publicKey:
|
|
387
|
+
signature: signatureSanitized,
|
|
388
|
+
publicKey: publicKeySanitized,
|
|
360
389
|
};
|
|
361
390
|
const options = {
|
|
362
391
|
method: 'POST',
|
|
@@ -368,8 +397,8 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
368
397
|
let pubKey;
|
|
369
398
|
let privKey;
|
|
370
399
|
try {
|
|
371
|
-
pubKey =
|
|
372
|
-
privKey =
|
|
400
|
+
pubKey = TKMS.u8vec_to_ml_kem_pke_pk(fromHexString(publicKey));
|
|
401
|
+
privKey = TKMS.u8vec_to_ml_kem_pke_sk(fromHexString(privateKey));
|
|
373
402
|
}
|
|
374
403
|
catch (e) {
|
|
375
404
|
throw new Error('Invalid public or private key', { cause: e });
|
|
@@ -400,9 +429,9 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
400
429
|
}
|
|
401
430
|
// assume the KMS Signers have the correct order
|
|
402
431
|
let indexedKmsSigners = kmsSigners.map((signer, index) => {
|
|
403
|
-
return
|
|
432
|
+
return TKMS.new_server_id_addr(index + 1, signer);
|
|
404
433
|
});
|
|
405
|
-
const client =
|
|
434
|
+
const client = TKMS.new_client(indexedKmsSigners, userAddress, 'default');
|
|
406
435
|
try {
|
|
407
436
|
const buffer = new ArrayBuffer(32);
|
|
408
437
|
const view = new DataView(buffer);
|
|
@@ -416,13 +445,13 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
416
445
|
salt: null,
|
|
417
446
|
};
|
|
418
447
|
const payloadForVerification = {
|
|
419
|
-
signature,
|
|
448
|
+
signature: signatureSanitized,
|
|
420
449
|
client_address: userAddress,
|
|
421
|
-
enc_key:
|
|
450
|
+
enc_key: publicKeySanitized,
|
|
422
451
|
ciphertext_handles: handles.map((h) => h.handle.replace(/^0x/, '')),
|
|
423
452
|
eip712_verifying_contract: verifyingContractAddress,
|
|
424
453
|
};
|
|
425
|
-
const decryption =
|
|
454
|
+
const decryption = TKMS.process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json.response, pubKey, privKey, true);
|
|
426
455
|
const listBigIntDecryptions = decryption.map((d) => bytesToBigInt(d.bytes));
|
|
427
456
|
const results = buildUserDecryptedResult(handles.map((h) => h.handle), listBigIntDecryptions);
|
|
428
457
|
return results;
|
|
@@ -457,7 +486,7 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
|
|
|
457
486
|
}
|
|
458
487
|
const publicKey = tfheCompactPublicKey;
|
|
459
488
|
const bits = [];
|
|
460
|
-
const builder =
|
|
489
|
+
const builder = TFHE.CompactCiphertextList.builder(publicKey);
|
|
461
490
|
let ciphertextWithZKProof = new Uint8Array(); // updated in `_prove`
|
|
462
491
|
const checkLimit = (added) => {
|
|
463
492
|
if (bits.reduce((acc, val) => acc + Math.max(2, val), 0) + added > 2048) {
|
|
@@ -588,7 +617,7 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
|
|
|
588
617
|
auxData.set(buffUser, 20);
|
|
589
618
|
auxData.set(buffAcl, 40);
|
|
590
619
|
auxData.set(buffChainId, auxData.length - buffChainId.length);
|
|
591
|
-
const encrypted = builder.build_with_proof_packed(pp, auxData,
|
|
620
|
+
const encrypted = builder.build_with_proof_packed(pp, auxData, TFHE.ZkComputeLoad.Verify);
|
|
592
621
|
ciphertextWithZKProof = encrypted.safe_serialize(SERIALIZED_SIZE_LIMIT_CIPHERTEXT);
|
|
593
622
|
return ciphertextWithZKProof;
|
|
594
623
|
},
|
|
@@ -634,9 +663,9 @@ const computeHandles = (ciphertextWithZKProof, bitwidths, aclContractAddress, ch
|
|
|
634
663
|
if (BigInt(chainId) > MAX_UINT64) {
|
|
635
664
|
throw new Error('ChainId exceeds maximum allowed value (8 bytes)'); // fhevm assumes chainID is only taking up to 8 bytes
|
|
636
665
|
}
|
|
637
|
-
const chainId8Bytes =
|
|
666
|
+
const chainId8Bytes = fromHexString(hex).slice(24, 32);
|
|
638
667
|
dataInput[21] = encryptionIndex;
|
|
639
|
-
|
|
668
|
+
dataInput.set(chainId8Bytes, 22);
|
|
640
669
|
dataInput[30] = encryptionType;
|
|
641
670
|
dataInput[31] = ciphertextVersion;
|
|
642
671
|
return dataInput;
|
|
@@ -988,7 +1017,7 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
|
|
|
988
1017
|
* @param durationDays - How many days the decryption permission remains valid
|
|
989
1018
|
* @returns EIP712 typed data structure for user decryption
|
|
990
1019
|
*/
|
|
991
|
-
const createEIP712 = (
|
|
1020
|
+
const createEIP712 = (verifyingContract, contractsChainId) => (publicKey, contractAddresses, startTimestamp, durationDays, delegatedAccount) => {
|
|
992
1021
|
if (delegatedAccount && !ethers.isAddress(delegatedAccount))
|
|
993
1022
|
throw new Error('Invalid delegated account.');
|
|
994
1023
|
if (!ethers.isAddress(verifyingContract)) {
|
|
@@ -1017,7 +1046,7 @@ const createEIP712 = (gatewayChainId, verifyingContract, contractsChainId) => (p
|
|
|
1017
1046
|
const domain = {
|
|
1018
1047
|
name: 'Decryption',
|
|
1019
1048
|
version: '1',
|
|
1020
|
-
chainId:
|
|
1049
|
+
chainId: contractsChainId,
|
|
1021
1050
|
verifyingContract,
|
|
1022
1051
|
};
|
|
1023
1052
|
if (delegatedAccount) {
|
|
@@ -1071,14 +1100,34 @@ const createEIP712 = (gatewayChainId, verifyingContract, contractsChainId) => (p
|
|
|
1071
1100
|
};
|
|
1072
1101
|
};
|
|
1073
1102
|
const generateKeypair = () => {
|
|
1074
|
-
const keypair =
|
|
1103
|
+
const keypair = TKMS.ml_kem_pke_keygen();
|
|
1075
1104
|
return {
|
|
1076
|
-
publicKey: toHexString(
|
|
1077
|
-
privateKey: toHexString(
|
|
1105
|
+
publicKey: toHexString(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
|
|
1106
|
+
privateKey: toHexString(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
|
|
1078
1107
|
};
|
|
1079
1108
|
};
|
|
1080
1109
|
|
|
1081
1110
|
global.fetch = fetchRetry(global.fetch, { retries: 5, retryDelay: 500 });
|
|
1111
|
+
const SepoliaConfig = {
|
|
1112
|
+
// ACL_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1113
|
+
aclContractAddress: '0x687820221192C5B662b25367F70076A37bc79b6c',
|
|
1114
|
+
// KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1115
|
+
kmsContractAddress: '0x1364cBBf2cDF5032C47d8226a6f6FBD2AFCDacAC',
|
|
1116
|
+
// INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1117
|
+
inputVerifierContractAddress: '0xbc91f3daD1A5F19F8390c400196e58073B6a0BC4',
|
|
1118
|
+
// DECRYPTION_ADDRESS (Gateway chain)
|
|
1119
|
+
verifyingContractAddressDecryption: '0xb6E160B1ff80D67Bfe90A85eE06Ce0A2613607D1',
|
|
1120
|
+
// INPUT_VERIFICATION_ADDRESS (Gateway chain)
|
|
1121
|
+
verifyingContractAddressInputVerification: '0x7048C39f048125eDa9d678AEbaDfB22F7900a29F',
|
|
1122
|
+
// FHEVM Host chain id
|
|
1123
|
+
chainId: 11155111,
|
|
1124
|
+
// Gateway chain id
|
|
1125
|
+
gatewayChainId: 55815,
|
|
1126
|
+
// Optional RPC provider to host chain
|
|
1127
|
+
network: 'https://eth-sepolia.public.blastapi.io',
|
|
1128
|
+
// Relayer URL
|
|
1129
|
+
relayerUrl: 'https://relayer.testnet.zama.cloud',
|
|
1130
|
+
};
|
|
1082
1131
|
const createInstance = async (config) => {
|
|
1083
1132
|
const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, } = config;
|
|
1084
1133
|
if (!kmsContractAddress || !ethers.isAddress(kmsContractAddress)) {
|
|
@@ -1111,7 +1160,7 @@ const createInstance = async (config) => {
|
|
|
1111
1160
|
return {
|
|
1112
1161
|
createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, cleanURL(config.relayerUrl), publicKeyData.publicKey, publicParamsData, coprocessorSigners, thresholdCoprocessorSigners),
|
|
1113
1162
|
generateKeypair,
|
|
1114
|
-
createEIP712: createEIP712(
|
|
1163
|
+
createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
|
|
1115
1164
|
publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
|
|
1116
1165
|
userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
|
|
1117
1166
|
getPublicKey: () => publicKeyData.publicKey
|
|
@@ -1133,15 +1182,15 @@ const createInstance = async (config) => {
|
|
|
1133
1182
|
};
|
|
1134
1183
|
|
|
1135
1184
|
const createTfheKeypair = () => {
|
|
1136
|
-
const block_params = new
|
|
1137
|
-
const casting_params = new
|
|
1138
|
-
const config =
|
|
1185
|
+
const block_params = new TFHEPkg.ShortintParameters(TFHEPkg.ShortintParametersName.PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
|
|
1186
|
+
const casting_params = new TFHEPkg.ShortintCompactPublicKeyEncryptionParameters(TFHEPkg.ShortintCompactPublicKeyEncryptionParametersName.V1_0_PARAM_PKE_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128);
|
|
1187
|
+
const config = TFHEPkg.TfheConfigBuilder.default()
|
|
1139
1188
|
.use_custom_parameters(block_params)
|
|
1140
1189
|
.use_dedicated_compact_public_key_parameters(casting_params)
|
|
1141
1190
|
.build();
|
|
1142
|
-
let clientKey =
|
|
1143
|
-
let publicKey =
|
|
1144
|
-
const crs =
|
|
1191
|
+
let clientKey = TFHEPkg.TfheClientKey.generate(config);
|
|
1192
|
+
let publicKey = TFHEPkg.TfheCompactPublicKey.new(clientKey);
|
|
1193
|
+
const crs = TFHEPkg.CompactPkeCrs.from_config(config, 4 * 512);
|
|
1145
1194
|
return { clientKey, publicKey, crs };
|
|
1146
1195
|
};
|
|
1147
1196
|
const createTfhePublicKey = () => {
|
|
@@ -1149,7 +1198,11 @@ const createTfhePublicKey = () => {
|
|
|
1149
1198
|
return toHexString(publicKey.serialize());
|
|
1150
1199
|
};
|
|
1151
1200
|
|
|
1201
|
+
global.TFHE = TFHEPkg__namespace;
|
|
1202
|
+
global.TKMS = TKMSPkg__namespace;
|
|
1203
|
+
|
|
1152
1204
|
exports.ENCRYPTION_TYPES = ENCRYPTION_TYPES;
|
|
1205
|
+
exports.SepoliaConfig = SepoliaConfig;
|
|
1153
1206
|
exports.createEIP712 = createEIP712;
|
|
1154
1207
|
exports.createInstance = createInstance;
|
|
1155
1208
|
exports.createTfheKeypair = createTfheKeypair;
|
package/lib/node.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { TfheCompactPublicKey } from 'node-tfhe';
|
|
|
15
15
|
* @param durationDays - How many days the decryption permission remains valid
|
|
16
16
|
* @returns EIP712 typed data structure for user decryption
|
|
17
17
|
*/
|
|
18
|
-
export declare const createEIP712: (
|
|
18
|
+
export declare const createEIP712: (verifyingContract: string, contractsChainId: number) => (publicKey: string | Uint8Array, contractAddresses: string[], startTimestamp: string | number, durationDays: string | number, delegatedAccount?: string) => EIP712;
|
|
19
19
|
|
|
20
20
|
export declare const createInstance: (config: FhevmInstanceConfig) => Promise<FhevmInstance>;
|
|
21
21
|
|
|
@@ -110,7 +110,7 @@ export declare type HandleContractPair = {
|
|
|
110
110
|
contractAddress: string;
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
export declare type PublicParams<T = CompactPkeCrs> = {
|
|
113
|
+
export declare type PublicParams<T = TFHE['CompactPkeCrs']> = {
|
|
114
114
|
[key in EncryptionTypes]?: {
|
|
115
115
|
publicParams: T;
|
|
116
116
|
publicParamsId: string;
|
|
@@ -136,4 +136,6 @@ export declare type RelayerEncryptedInput = {
|
|
|
136
136
|
}>;
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
+
export declare const SepoliaConfig: FhevmInstanceConfig;
|
|
140
|
+
|
|
139
141
|
export { }
|
package/lib/node.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as TFHEPkg from 'node-tfhe';
|
|
2
|
+
import { ShortintParameters, ShortintParametersName, ShortintCompactPublicKeyEncryptionParameters, ShortintCompactPublicKeyEncryptionParametersName, TfheConfigBuilder, TfheClientKey, TfheCompactPublicKey, CompactPkeCrs } from 'node-tfhe';
|
|
3
|
+
import * as TKMSPkg from 'node-tkms';
|
|
1
4
|
import { JsonRpcProvider, BrowserProvider, Contract, ethers, getAddress, isAddress, AbiCoder } from 'ethers';
|
|
2
|
-
import { TfheCompactPublicKey, CompactPkeCrs, CompactCiphertextList, ZkComputeLoad, ShortintParameters, ShortintParametersName, ShortintCompactPublicKeyEncryptionParameters, ShortintCompactPublicKeyEncryptionParametersName, TfheConfigBuilder, TfheClientKey } from 'node-tfhe';
|
|
3
|
-
import { u8vec_to_ml_kem_pke_pk, u8vec_to_ml_kem_pke_sk, new_server_id_addr, new_client, process_user_decryption_resp_from_js, ml_kem_pke_keygen, ml_kem_pke_pk_to_u8vec, ml_kem_pke_get_pk, ml_kem_pke_sk_to_u8vec } from 'node-tkms';
|
|
4
5
|
import createHash from 'keccak';
|
|
5
6
|
import fetchRetry from 'fetch-retry';
|
|
6
7
|
|
|
@@ -80,10 +81,17 @@ const getKeysFromRelayer = async (url, publicKeyId) => {
|
|
|
80
81
|
if (!publicParams2048Response.ok) {
|
|
81
82
|
throw new Error(`HTTP error! status: ${publicParams2048Response.status} on ${publicParams2048Response.url}`);
|
|
82
83
|
}
|
|
83
|
-
|
|
84
|
+
let publicParams2048;
|
|
85
|
+
if (typeof publicParams2048Response.bytes === 'function') {
|
|
86
|
+
// bytes is not widely supported yet
|
|
87
|
+
publicParams2048 = await publicParams2048Response.bytes();
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
publicParams2048 = new Uint8Array(await publicParams2048Response.arrayBuffer());
|
|
91
|
+
}
|
|
84
92
|
let pub_key;
|
|
85
93
|
try {
|
|
86
|
-
pub_key = TfheCompactPublicKey.safe_deserialize(publicKey, SERIALIZED_SIZE_LIMIT_PK);
|
|
94
|
+
pub_key = TFHE.TfheCompactPublicKey.safe_deserialize(publicKey, SERIALIZED_SIZE_LIMIT_PK);
|
|
87
95
|
}
|
|
88
96
|
catch (e) {
|
|
89
97
|
throw new Error('Invalid public key (deserialization failed)', {
|
|
@@ -92,7 +100,7 @@ const getKeysFromRelayer = async (url, publicKeyId) => {
|
|
|
92
100
|
}
|
|
93
101
|
let crs;
|
|
94
102
|
try {
|
|
95
|
-
crs = CompactPkeCrs.safe_deserialize(new Uint8Array(publicParams2048), SERIALIZED_SIZE_LIMIT_CRS);
|
|
103
|
+
crs = TFHE.CompactPkeCrs.safe_deserialize(new Uint8Array(publicParams2048), SERIALIZED_SIZE_LIMIT_CRS);
|
|
96
104
|
}
|
|
97
105
|
catch (e) {
|
|
98
106
|
throw new Error('Invalid crs (deserialization failed)', {
|
|
@@ -161,7 +169,7 @@ const getTfheCompactPublicKey = async (config) => {
|
|
|
161
169
|
const buff = config.publicKey.data;
|
|
162
170
|
try {
|
|
163
171
|
return {
|
|
164
|
-
publicKey: TfheCompactPublicKey.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_PK),
|
|
172
|
+
publicKey: TFHE.TfheCompactPublicKey.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_PK),
|
|
165
173
|
publicKeyId: config.publicKey.id,
|
|
166
174
|
};
|
|
167
175
|
}
|
|
@@ -185,7 +193,7 @@ const getPublicParams = async (config) => {
|
|
|
185
193
|
try {
|
|
186
194
|
return {
|
|
187
195
|
2048: {
|
|
188
|
-
publicParams: CompactPkeCrs.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_CRS),
|
|
196
|
+
publicParams: TFHE.CompactPkeCrs.safe_deserialize(buff, SERIALIZED_SIZE_LIMIT_CRS),
|
|
189
197
|
publicParamsId: config.publicParams['2048'].publicParamsId,
|
|
190
198
|
},
|
|
191
199
|
};
|
|
@@ -312,6 +320,8 @@ function checkDeadlineValidity(startTimestamp, durationDays) {
|
|
|
312
320
|
}
|
|
313
321
|
const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContractAddress, aclContractAddress, relayerUrl, provider) => async (_handles, privateKey, publicKey, signature, contractAddresses, userAddress, startTimestamp, durationDays) => {
|
|
314
322
|
// Casting handles if string
|
|
323
|
+
const signatureSanitized = signature.replace(/^(0x)/, '');
|
|
324
|
+
const publicKeySanitized = publicKey.replace(/^(0x)/, '');
|
|
315
325
|
const handles = _handles.map((h) => ({
|
|
316
326
|
handle: typeof h.handle === 'string'
|
|
317
327
|
? toHexString(fromHexString(h.handle), true)
|
|
@@ -353,8 +363,8 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
353
363
|
contractsChainId: chainId.toString(), // Convert to string
|
|
354
364
|
contractAddresses: contractAddresses.map((c) => getAddress(c)),
|
|
355
365
|
userAddress: getAddress(userAddress),
|
|
356
|
-
signature:
|
|
357
|
-
publicKey:
|
|
366
|
+
signature: signatureSanitized,
|
|
367
|
+
publicKey: publicKeySanitized,
|
|
358
368
|
};
|
|
359
369
|
const options = {
|
|
360
370
|
method: 'POST',
|
|
@@ -366,8 +376,8 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
366
376
|
let pubKey;
|
|
367
377
|
let privKey;
|
|
368
378
|
try {
|
|
369
|
-
pubKey = u8vec_to_ml_kem_pke_pk(fromHexString(publicKey));
|
|
370
|
-
privKey = u8vec_to_ml_kem_pke_sk(fromHexString(privateKey));
|
|
379
|
+
pubKey = TKMS.u8vec_to_ml_kem_pke_pk(fromHexString(publicKey));
|
|
380
|
+
privKey = TKMS.u8vec_to_ml_kem_pke_sk(fromHexString(privateKey));
|
|
371
381
|
}
|
|
372
382
|
catch (e) {
|
|
373
383
|
throw new Error('Invalid public or private key', { cause: e });
|
|
@@ -398,9 +408,9 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
398
408
|
}
|
|
399
409
|
// assume the KMS Signers have the correct order
|
|
400
410
|
let indexedKmsSigners = kmsSigners.map((signer, index) => {
|
|
401
|
-
return new_server_id_addr(index + 1, signer);
|
|
411
|
+
return TKMS.new_server_id_addr(index + 1, signer);
|
|
402
412
|
});
|
|
403
|
-
const client = new_client(indexedKmsSigners, userAddress, 'default');
|
|
413
|
+
const client = TKMS.new_client(indexedKmsSigners, userAddress, 'default');
|
|
404
414
|
try {
|
|
405
415
|
const buffer = new ArrayBuffer(32);
|
|
406
416
|
const view = new DataView(buffer);
|
|
@@ -414,13 +424,13 @@ const userDecryptRequest = (kmsSigners, gatewayChainId, chainId, verifyingContra
|
|
|
414
424
|
salt: null,
|
|
415
425
|
};
|
|
416
426
|
const payloadForVerification = {
|
|
417
|
-
signature,
|
|
427
|
+
signature: signatureSanitized,
|
|
418
428
|
client_address: userAddress,
|
|
419
|
-
enc_key:
|
|
429
|
+
enc_key: publicKeySanitized,
|
|
420
430
|
ciphertext_handles: handles.map((h) => h.handle.replace(/^0x/, '')),
|
|
421
431
|
eip712_verifying_contract: verifyingContractAddress,
|
|
422
432
|
};
|
|
423
|
-
const decryption = process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json.response, pubKey, privKey, true);
|
|
433
|
+
const decryption = TKMS.process_user_decryption_resp_from_js(client, payloadForVerification, eip712Domain, json.response, pubKey, privKey, true);
|
|
424
434
|
const listBigIntDecryptions = decryption.map((d) => bytesToBigInt(d.bytes));
|
|
425
435
|
const results = buildUserDecryptedResult(handles.map((h) => h.handle), listBigIntDecryptions);
|
|
426
436
|
return results;
|
|
@@ -455,7 +465,7 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
|
|
|
455
465
|
}
|
|
456
466
|
const publicKey = tfheCompactPublicKey;
|
|
457
467
|
const bits = [];
|
|
458
|
-
const builder = CompactCiphertextList.builder(publicKey);
|
|
468
|
+
const builder = TFHE.CompactCiphertextList.builder(publicKey);
|
|
459
469
|
let ciphertextWithZKProof = new Uint8Array(); // updated in `_prove`
|
|
460
470
|
const checkLimit = (added) => {
|
|
461
471
|
if (bits.reduce((acc, val) => acc + Math.max(2, val), 0) + added > 2048) {
|
|
@@ -586,7 +596,7 @@ const createEncryptedInput = ({ aclContractAddress, chainId, tfheCompactPublicKe
|
|
|
586
596
|
auxData.set(buffUser, 20);
|
|
587
597
|
auxData.set(buffAcl, 40);
|
|
588
598
|
auxData.set(buffChainId, auxData.length - buffChainId.length);
|
|
589
|
-
const encrypted = builder.build_with_proof_packed(pp, auxData, ZkComputeLoad.Verify);
|
|
599
|
+
const encrypted = builder.build_with_proof_packed(pp, auxData, TFHE.ZkComputeLoad.Verify);
|
|
590
600
|
ciphertextWithZKProof = encrypted.safe_serialize(SERIALIZED_SIZE_LIMIT_CIPHERTEXT);
|
|
591
601
|
return ciphertextWithZKProof;
|
|
592
602
|
},
|
|
@@ -632,9 +642,9 @@ const computeHandles = (ciphertextWithZKProof, bitwidths, aclContractAddress, ch
|
|
|
632
642
|
if (BigInt(chainId) > MAX_UINT64) {
|
|
633
643
|
throw new Error('ChainId exceeds maximum allowed value (8 bytes)'); // fhevm assumes chainID is only taking up to 8 bytes
|
|
634
644
|
}
|
|
635
|
-
const chainId8Bytes =
|
|
645
|
+
const chainId8Bytes = fromHexString(hex).slice(24, 32);
|
|
636
646
|
dataInput[21] = encryptionIndex;
|
|
637
|
-
|
|
647
|
+
dataInput.set(chainId8Bytes, 22);
|
|
638
648
|
dataInput[30] = encryptionType;
|
|
639
649
|
dataInput[31] = ciphertextVersion;
|
|
640
650
|
return dataInput;
|
|
@@ -986,7 +996,7 @@ const publicDecryptRequest = (kmsSigners, thresholdSigners, gatewayChainId, veri
|
|
|
986
996
|
* @param durationDays - How many days the decryption permission remains valid
|
|
987
997
|
* @returns EIP712 typed data structure for user decryption
|
|
988
998
|
*/
|
|
989
|
-
const createEIP712 = (
|
|
999
|
+
const createEIP712 = (verifyingContract, contractsChainId) => (publicKey, contractAddresses, startTimestamp, durationDays, delegatedAccount) => {
|
|
990
1000
|
if (delegatedAccount && !isAddress(delegatedAccount))
|
|
991
1001
|
throw new Error('Invalid delegated account.');
|
|
992
1002
|
if (!isAddress(verifyingContract)) {
|
|
@@ -1015,7 +1025,7 @@ const createEIP712 = (gatewayChainId, verifyingContract, contractsChainId) => (p
|
|
|
1015
1025
|
const domain = {
|
|
1016
1026
|
name: 'Decryption',
|
|
1017
1027
|
version: '1',
|
|
1018
|
-
chainId:
|
|
1028
|
+
chainId: contractsChainId,
|
|
1019
1029
|
verifyingContract,
|
|
1020
1030
|
};
|
|
1021
1031
|
if (delegatedAccount) {
|
|
@@ -1069,14 +1079,34 @@ const createEIP712 = (gatewayChainId, verifyingContract, contractsChainId) => (p
|
|
|
1069
1079
|
};
|
|
1070
1080
|
};
|
|
1071
1081
|
const generateKeypair = () => {
|
|
1072
|
-
const keypair = ml_kem_pke_keygen();
|
|
1082
|
+
const keypair = TKMS.ml_kem_pke_keygen();
|
|
1073
1083
|
return {
|
|
1074
|
-
publicKey: toHexString(ml_kem_pke_pk_to_u8vec(ml_kem_pke_get_pk(keypair))),
|
|
1075
|
-
privateKey: toHexString(ml_kem_pke_sk_to_u8vec(keypair)),
|
|
1084
|
+
publicKey: toHexString(TKMS.ml_kem_pke_pk_to_u8vec(TKMS.ml_kem_pke_get_pk(keypair))),
|
|
1085
|
+
privateKey: toHexString(TKMS.ml_kem_pke_sk_to_u8vec(keypair)),
|
|
1076
1086
|
};
|
|
1077
1087
|
};
|
|
1078
1088
|
|
|
1079
1089
|
global.fetch = fetchRetry(global.fetch, { retries: 5, retryDelay: 500 });
|
|
1090
|
+
const SepoliaConfig = {
|
|
1091
|
+
// ACL_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1092
|
+
aclContractAddress: '0x687820221192C5B662b25367F70076A37bc79b6c',
|
|
1093
|
+
// KMS_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1094
|
+
kmsContractAddress: '0x1364cBBf2cDF5032C47d8226a6f6FBD2AFCDacAC',
|
|
1095
|
+
// INPUT_VERIFIER_CONTRACT_ADDRESS (FHEVM Host chain)
|
|
1096
|
+
inputVerifierContractAddress: '0xbc91f3daD1A5F19F8390c400196e58073B6a0BC4',
|
|
1097
|
+
// DECRYPTION_ADDRESS (Gateway chain)
|
|
1098
|
+
verifyingContractAddressDecryption: '0xb6E160B1ff80D67Bfe90A85eE06Ce0A2613607D1',
|
|
1099
|
+
// INPUT_VERIFICATION_ADDRESS (Gateway chain)
|
|
1100
|
+
verifyingContractAddressInputVerification: '0x7048C39f048125eDa9d678AEbaDfB22F7900a29F',
|
|
1101
|
+
// FHEVM Host chain id
|
|
1102
|
+
chainId: 11155111,
|
|
1103
|
+
// Gateway chain id
|
|
1104
|
+
gatewayChainId: 55815,
|
|
1105
|
+
// Optional RPC provider to host chain
|
|
1106
|
+
network: 'https://eth-sepolia.public.blastapi.io',
|
|
1107
|
+
// Relayer URL
|
|
1108
|
+
relayerUrl: 'https://relayer.testnet.zama.cloud',
|
|
1109
|
+
};
|
|
1080
1110
|
const createInstance = async (config) => {
|
|
1081
1111
|
const { verifyingContractAddressDecryption, verifyingContractAddressInputVerification, publicKey, kmsContractAddress, aclContractAddress, gatewayChainId, } = config;
|
|
1082
1112
|
if (!kmsContractAddress || !isAddress(kmsContractAddress)) {
|
|
@@ -1109,7 +1139,7 @@ const createInstance = async (config) => {
|
|
|
1109
1139
|
return {
|
|
1110
1140
|
createEncryptedInput: createRelayerEncryptedInput(aclContractAddress, verifyingContractAddressInputVerification, chainId, gatewayChainId, cleanURL(config.relayerUrl), publicKeyData.publicKey, publicParamsData, coprocessorSigners, thresholdCoprocessorSigners),
|
|
1111
1141
|
generateKeypair,
|
|
1112
|
-
createEIP712: createEIP712(
|
|
1142
|
+
createEIP712: createEIP712(verifyingContractAddressDecryption, chainId),
|
|
1113
1143
|
publicDecrypt: publicDecryptRequest(kmsSigners, thresholdKMSSigners, gatewayChainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
|
|
1114
1144
|
userDecrypt: userDecryptRequest(kmsSigners, gatewayChainId, chainId, verifyingContractAddressDecryption, aclContractAddress, cleanURL(config.relayerUrl), provider),
|
|
1115
1145
|
getPublicKey: () => publicKeyData.publicKey
|
|
@@ -1147,4 +1177,7 @@ const createTfhePublicKey = () => {
|
|
|
1147
1177
|
return toHexString(publicKey.serialize());
|
|
1148
1178
|
};
|
|
1149
1179
|
|
|
1150
|
-
|
|
1180
|
+
global.TFHE = TFHEPkg;
|
|
1181
|
+
global.TKMS = TKMSPkg;
|
|
1182
|
+
|
|
1183
|
+
export { ENCRYPTION_TYPES, SepoliaConfig, createEIP712, createInstance, createTfheKeypair, createTfhePublicKey, generateKeypair };
|
package/lib/tfhe_bg.wasm
CHANGED
|
Binary file
|
package/lib/web.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CompactPkeCrs } from 'node-tfhe';
|
|
2
1
|
import { Eip1193Provider } from 'ethers';
|
|
3
2
|
import { InitInput as KMSInput } from 'tkms';
|
|
4
3
|
import { InitInput as TFHEInput } from 'tfhe';
|
|
@@ -15,7 +14,7 @@ import { InitInput as TFHEInput } from 'tfhe';
|
|
|
15
14
|
* @param durationDays - How many days the decryption permission remains valid
|
|
16
15
|
* @returns EIP712 typed data structure for user decryption
|
|
17
16
|
*/
|
|
18
|
-
export declare const createEIP712: (
|
|
17
|
+
export declare const createEIP712: (verifyingContract: string, contractsChainId: number) => (publicKey: string | Uint8Array, contractAddresses: string[], startTimestamp: string | number, durationDays: string | number, delegatedAccount?: string) => EIP712;
|
|
19
18
|
|
|
20
19
|
export declare const createInstance: (config: FhevmInstanceConfig) => Promise<FhevmInstance>;
|
|
21
20
|
|
|
@@ -110,7 +109,7 @@ export declare const initFhevm: ({ tfheParams, kmsParams, thread, }?: {
|
|
|
110
109
|
|
|
111
110
|
export { KMSInput }
|
|
112
111
|
|
|
113
|
-
export declare type PublicParams<T = CompactPkeCrs> = {
|
|
112
|
+
export declare type PublicParams<T = TFHE['CompactPkeCrs']> = {
|
|
114
113
|
[key in EncryptionTypes]?: {
|
|
115
114
|
publicParams: T;
|
|
116
115
|
publicParamsId: string;
|
|
@@ -136,6 +135,8 @@ export declare type RelayerEncryptedInput = {
|
|
|
136
135
|
}>;
|
|
137
136
|
};
|
|
138
137
|
|
|
138
|
+
export declare const SepoliaConfig: FhevmInstanceConfig;
|
|
139
|
+
|
|
139
140
|
export { TFHEInput }
|
|
140
141
|
|
|
141
142
|
export { }
|