@cofhe/sdk 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/adapters/{ethers5.test.ts → test/ethers5.test.ts} +2 -2
- package/adapters/{ethers6.test.ts → test/ethers6.test.ts} +2 -2
- package/adapters/{hardhat.hh2.test.ts → test/hardhat.hh2.test.ts} +2 -2
- package/adapters/{index.test.ts → test/index.test.ts} +1 -1
- package/adapters/{wagmi.test.ts → test/wagmi.test.ts} +1 -1
- package/chains/{chains.test.ts → test/chains.test.ts} +1 -1
- package/core/client.ts +15 -5
- package/core/clientTypes.ts +7 -5
- package/core/consts.ts +9 -0
- package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
- package/core/decrypt/decryptForTxBuilder.ts +24 -10
- package/core/decrypt/decryptForViewBuilder.ts +14 -7
- package/core/decrypt/polling.ts +14 -0
- package/core/decrypt/tnDecryptUtils.ts +65 -0
- package/core/decrypt/{tnDecrypt.ts → tnDecryptV1.ts} +7 -70
- package/core/decrypt/tnDecryptV2.ts +483 -0
- package/core/decrypt/tnSealOutputV2.ts +245 -104
- package/core/decrypt/verifyDecryptResult.ts +65 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
- package/core/encrypt/zkPackProveVerify.ts +10 -19
- package/core/fetchKeys.ts +0 -2
- package/core/index.ts +9 -1
- package/core/keyStore.ts +5 -2
- package/core/permits.ts +8 -3
- package/core/{client.test.ts → test/client.test.ts} +7 -7
- package/core/{config.test.ts → test/config.test.ts} +1 -1
- package/core/test/decrypt.test.ts +252 -0
- package/core/test/decryptBuilders.test.ts +390 -0
- package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
- package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
- package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
- package/core/{permits.test.ts → test/permits.test.ts} +42 -1
- package/core/test/pollCallbacks.test.ts +563 -0
- package/core/types.ts +21 -0
- package/dist/chains.d.cts +2 -2
- package/dist/chains.d.ts +2 -2
- package/dist/chunk-4FP4V35O.js +13 -0
- package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
- package/dist/{chunk-LWMRB6SD.js → chunk-S7OKGLFD.js} +615 -198
- package/dist/{clientTypes-Y43CKbOz.d.cts → clientTypes-BSbwairE.d.cts} +38 -13
- package/dist/{clientTypes-PQha8zes.d.ts → clientTypes-DDmcgZ0a.d.ts} +38 -13
- package/dist/core.cjs +691 -235
- package/dist/core.d.cts +24 -6
- package/dist/core.d.ts +24 -6
- package/dist/core.js +3 -2
- package/dist/node.cjs +696 -237
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +14 -7
- package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.cts} +34 -4
- package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.ts} +34 -4
- package/dist/permits.cjs +66 -29
- package/dist/permits.d.cts +18 -13
- package/dist/permits.d.ts +18 -13
- package/dist/permits.js +2 -1
- package/dist/web.cjs +718 -242
- package/dist/web.d.cts +8 -4
- package/dist/web.d.ts +8 -4
- package/dist/web.js +34 -11
- package/dist/zkProve.worker.cjs +6 -3
- package/dist/zkProve.worker.js +5 -3
- package/node/index.ts +13 -4
- package/node/test/client.test.ts +25 -0
- package/node/test/config.test.ts +16 -0
- package/node/test/inherited.test.ts +244 -0
- package/node/test/tfheinit.test.ts +56 -0
- package/package.json +24 -22
- package/permits/permit.ts +31 -5
- package/permits/sealing.ts +1 -1
- package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
- package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
- package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
- package/permits/{store.test.ts → test/store.test.ts} +2 -2
- package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
- package/permits/types.ts +1 -1
- package/permits/validation.ts +42 -2
- package/web/const.ts +2 -0
- package/web/index.ts +20 -6
- package/web/storage.ts +18 -3
- package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
- package/web/test/config.web.test.ts +16 -0
- package/web/test/inherited.web.test.ts +245 -0
- package/web/test/tfheinit.web.test.ts +62 -0
- package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
- package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
- package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
- package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
- package/web/zkProve.worker.ts +4 -3
- package/node/client.test.ts +0 -147
- package/node/config.test.ts +0 -68
- package/node/encryptInputs.test.ts +0 -155
- package/web/config.web.test.ts +0 -69
- package/web/encryptInputs.web.test.ts +0 -172
- package/web/worker.builder.web.test.ts +0 -148
- /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
- /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
package/dist/web.d.cts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-
|
|
1
|
+
import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-BSbwairE.cjs';
|
|
2
2
|
import 'viem';
|
|
3
|
-
import './types-
|
|
3
|
+
import './types-C07FK-cL.cjs';
|
|
4
4
|
import 'zod';
|
|
5
|
-
import './permit-
|
|
5
|
+
import './permit-DnVMDT5h.cjs';
|
|
6
6
|
import 'zustand/vanilla';
|
|
7
7
|
|
|
8
|
+
declare function createSsrStorage(): IStorage;
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
11
|
* Terminate the worker
|
|
10
12
|
*/
|
|
@@ -14,6 +16,8 @@ declare function terminateWorker(): void;
|
|
|
14
16
|
*/
|
|
15
17
|
declare function areWorkersAvailable(): boolean;
|
|
16
18
|
|
|
19
|
+
declare const hasDOM: boolean;
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* Creates a CoFHE configuration for web with IndexedDB storage as default
|
|
19
23
|
* @param config - The CoFHE input configuration (fheKeyStorage will default to IndexedDB if not provided)
|
|
@@ -35,4 +39,4 @@ declare function createCofheClient<TConfig extends CofheConfig>(config: TConfig)
|
|
|
35
39
|
*/
|
|
36
40
|
declare function createCofheClientWithCustomWorker(config: CofheConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofheClient;
|
|
37
41
|
|
|
38
|
-
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, terminateWorker };
|
|
42
|
+
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
|
package/dist/web.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-
|
|
1
|
+
import { I as IStorage, C as CofheInputConfig, a as CofheConfig, b as CofheClient, E as EncryptableItem } from './clientTypes-DDmcgZ0a.js';
|
|
2
2
|
import 'viem';
|
|
3
|
-
import './types-
|
|
3
|
+
import './types-C07FK-cL.js';
|
|
4
4
|
import 'zod';
|
|
5
|
-
import './permit-
|
|
5
|
+
import './permit-DnVMDT5h.js';
|
|
6
6
|
import 'zustand/vanilla';
|
|
7
7
|
|
|
8
|
+
declare function createSsrStorage(): IStorage;
|
|
9
|
+
|
|
8
10
|
/**
|
|
9
11
|
* Terminate the worker
|
|
10
12
|
*/
|
|
@@ -14,6 +16,8 @@ declare function terminateWorker(): void;
|
|
|
14
16
|
*/
|
|
15
17
|
declare function areWorkersAvailable(): boolean;
|
|
16
18
|
|
|
19
|
+
declare const hasDOM: boolean;
|
|
20
|
+
|
|
17
21
|
/**
|
|
18
22
|
* Creates a CoFHE configuration for web with IndexedDB storage as default
|
|
19
23
|
* @param config - The CoFHE input configuration (fheKeyStorage will default to IndexedDB if not provided)
|
|
@@ -35,4 +39,4 @@ declare function createCofheClient<TConfig extends CofheConfig>(config: TConfig)
|
|
|
35
39
|
*/
|
|
36
40
|
declare function createCofheClientWithCustomWorker(config: CofheConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofheClient;
|
|
37
41
|
|
|
38
|
-
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, terminateWorker };
|
|
42
|
+
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
|
package/dist/web.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
-
import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-
|
|
1
|
+
import { createCofheConfigBase, createCofheClientBase, fheTypeToString } from './chunk-S7OKGLFD.js';
|
|
2
2
|
import './chunk-TBLR7NNE.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-MRCKUMOS.js';
|
|
4
|
+
import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-4FP4V35O.js';
|
|
4
5
|
import { constructClient } from 'iframe-shared-storage';
|
|
5
|
-
import init, { init_panic_hook,
|
|
6
|
+
import init, { init_panic_hook, ProvenCompactCiphertextList, CompactPkeCrs, TfheCompactPublicKey } from 'tfhe';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// web/const.ts
|
|
9
|
+
var hasDOM = typeof globalThis?.document !== "undefined" && typeof globalThis?.window !== "undefined";
|
|
10
|
+
|
|
11
|
+
// web/storage.ts
|
|
12
|
+
var createWebStorage = (opts = { enableLog: false }) => {
|
|
13
|
+
if (!hasDOM)
|
|
14
|
+
throw new Error("createWebStorage can only be used in a browser environment");
|
|
8
15
|
const client = constructClient({
|
|
9
16
|
iframe: {
|
|
10
17
|
src: "https://iframe-shared-storage.vercel.app/hub.html",
|
|
11
18
|
messagingOptions: {
|
|
12
|
-
enableLog: "both"
|
|
19
|
+
enableLog: opts.enableLog ? "both" : void 0
|
|
13
20
|
},
|
|
14
21
|
iframeReadyTimeoutMs: 3e4,
|
|
15
22
|
// if the iframe is not initied during this interval AND a reuqest is made, such request will throw an error
|
|
@@ -32,6 +39,16 @@ var createWebStorage = () => {
|
|
|
32
39
|
}
|
|
33
40
|
};
|
|
34
41
|
};
|
|
42
|
+
function createSsrStorage() {
|
|
43
|
+
console.warn("using no-op server-side SSR storage");
|
|
44
|
+
return {
|
|
45
|
+
getItem: async () => null,
|
|
46
|
+
setItem: async () => {
|
|
47
|
+
},
|
|
48
|
+
removeItem: async () => {
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
35
52
|
|
|
36
53
|
// web/workerManager.ts
|
|
37
54
|
var ZkProveWorkerManager = class {
|
|
@@ -187,16 +204,22 @@ var fromHexString = (hexString) => {
|
|
|
187
204
|
return new Uint8Array();
|
|
188
205
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
189
206
|
};
|
|
207
|
+
var _deserializeTfhePublicKey = (buff) => {
|
|
208
|
+
return TfheCompactPublicKey.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
209
|
+
};
|
|
210
|
+
var _deserializeCompactPkeCrs = (buff) => {
|
|
211
|
+
return CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
212
|
+
};
|
|
190
213
|
var tfhePublicKeyDeserializer = (buff) => {
|
|
191
|
-
|
|
214
|
+
_deserializeTfhePublicKey(buff);
|
|
192
215
|
};
|
|
193
216
|
var compactPkeCrsDeserializer = (buff) => {
|
|
194
|
-
|
|
217
|
+
_deserializeCompactPkeCrs(buff);
|
|
195
218
|
};
|
|
196
219
|
var zkBuilderAndCrsGenerator = (fhe, crs) => {
|
|
197
|
-
const fhePublicKey =
|
|
220
|
+
const fhePublicKey = _deserializeTfhePublicKey(fhe);
|
|
198
221
|
const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
|
|
199
|
-
const zkCrs =
|
|
222
|
+
const zkCrs = _deserializeCompactPkeCrs(crs);
|
|
200
223
|
return { zkBuilder, zkCrs };
|
|
201
224
|
};
|
|
202
225
|
async function zkProveWithWorker(fheKeyHex, crsHex, items, metadata) {
|
|
@@ -211,7 +234,7 @@ function createCofheConfig(config) {
|
|
|
211
234
|
return createCofheConfigBase({
|
|
212
235
|
environment: "web",
|
|
213
236
|
...config,
|
|
214
|
-
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createWebStorage()
|
|
237
|
+
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? (hasDOM ? createWebStorage() : createSsrStorage())
|
|
215
238
|
});
|
|
216
239
|
}
|
|
217
240
|
function createCofheClient(config) {
|
|
@@ -237,4 +260,4 @@ function createCofheClientWithCustomWorker(config, customZkProveWorkerFn) {
|
|
|
237
260
|
});
|
|
238
261
|
}
|
|
239
262
|
|
|
240
|
-
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, terminateWorker };
|
|
263
|
+
export { areWorkersAvailable, createCofheClient, createCofheClientWithCustomWorker, createCofheConfig, createSsrStorage, hasDOM, terminateWorker };
|
package/dist/zkProve.worker.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// core/consts.ts
|
|
4
|
+
var TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT = BigInt(1 << 30);
|
|
5
|
+
|
|
3
6
|
// web/zkProve.worker.ts
|
|
4
7
|
var tfheModule = null;
|
|
5
8
|
var initialized = false;
|
|
@@ -41,8 +44,8 @@ self.onmessage = async (event) => {
|
|
|
41
44
|
}
|
|
42
45
|
const fheKeyBytes = fromHexString(fheKeyHex);
|
|
43
46
|
const crsBytes = fromHexString(crsHex);
|
|
44
|
-
const fheKey = tfheModule.TfheCompactPublicKey.
|
|
45
|
-
const crs = tfheModule.CompactPkeCrs.
|
|
47
|
+
const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(fheKeyBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
48
|
+
const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
46
49
|
const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
|
|
47
50
|
for (const item of items) {
|
|
48
51
|
switch (item.utype) {
|
|
@@ -73,7 +76,7 @@ self.onmessage = async (event) => {
|
|
|
73
76
|
}
|
|
74
77
|
const metadataBytes = new Uint8Array(metadata);
|
|
75
78
|
const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
|
|
76
|
-
const result = compactList.
|
|
79
|
+
const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
77
80
|
self.postMessage({
|
|
78
81
|
id,
|
|
79
82
|
type: "success",
|
package/dist/zkProve.worker.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-4FP4V35O.js';
|
|
2
|
+
|
|
1
3
|
// web/zkProve.worker.ts
|
|
2
4
|
var tfheModule = null;
|
|
3
5
|
var initialized = false;
|
|
@@ -39,8 +41,8 @@ self.onmessage = async (event) => {
|
|
|
39
41
|
}
|
|
40
42
|
const fheKeyBytes = fromHexString(fheKeyHex);
|
|
41
43
|
const crsBytes = fromHexString(crsHex);
|
|
42
|
-
const fheKey = tfheModule.TfheCompactPublicKey.
|
|
43
|
-
const crs = tfheModule.CompactPkeCrs.
|
|
44
|
+
const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(fheKeyBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
45
|
+
const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
44
46
|
const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
|
|
45
47
|
for (const item of items) {
|
|
46
48
|
switch (item.utype) {
|
|
@@ -71,7 +73,7 @@ self.onmessage = async (event) => {
|
|
|
71
73
|
}
|
|
72
74
|
const metadataBytes = new Uint8Array(metadata);
|
|
73
75
|
const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
|
|
74
|
-
const result = compactList.
|
|
76
|
+
const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
75
77
|
self.postMessage({
|
|
76
78
|
id,
|
|
77
79
|
type: "success",
|
package/node/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type CofheInputConfig,
|
|
9
9
|
type ZkBuilderAndCrsGenerator,
|
|
10
10
|
type FheKeyDeserializer,
|
|
11
|
+
TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT,
|
|
11
12
|
} from '@/core';
|
|
12
13
|
|
|
13
14
|
// Import node-specific storage (internal use only)
|
|
@@ -39,12 +40,20 @@ const fromHexString = (hexString: string): Uint8Array => {
|
|
|
39
40
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
40
41
|
};
|
|
41
42
|
|
|
43
|
+
const _deserializeTfhePublicKey = (buff: string): TfheCompactPublicKey => {
|
|
44
|
+
return TfheCompactPublicKey.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const _deserializeCompactPkeCrs = (buff: string): CompactPkeCrs => {
|
|
48
|
+
return CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
|
|
49
|
+
};
|
|
50
|
+
|
|
42
51
|
/**
|
|
43
52
|
* Serializer for TFHE public keys
|
|
44
53
|
* Validates that the buffer can be deserialized into a TfheCompactPublicKey
|
|
45
54
|
*/
|
|
46
55
|
const tfhePublicKeyDeserializer: FheKeyDeserializer = (buff: string): void => {
|
|
47
|
-
|
|
56
|
+
_deserializeTfhePublicKey(buff);
|
|
48
57
|
};
|
|
49
58
|
|
|
50
59
|
/**
|
|
@@ -52,7 +61,7 @@ const tfhePublicKeyDeserializer: FheKeyDeserializer = (buff: string): void => {
|
|
|
52
61
|
* Validates that the buffer can be deserialized into ZkCompactPkePublicParams
|
|
53
62
|
*/
|
|
54
63
|
const compactPkeCrsDeserializer: FheKeyDeserializer = (buff: string): void => {
|
|
55
|
-
|
|
64
|
+
_deserializeCompactPkeCrs(buff);
|
|
56
65
|
};
|
|
57
66
|
|
|
58
67
|
/**
|
|
@@ -60,9 +69,9 @@ const compactPkeCrsDeserializer: FheKeyDeserializer = (buff: string): void => {
|
|
|
60
69
|
* This is used internally by the SDK to create encrypted inputs
|
|
61
70
|
*/
|
|
62
71
|
const zkBuilderAndCrsGenerator: ZkBuilderAndCrsGenerator = (fhe: string, crs: string) => {
|
|
63
|
-
const fhePublicKey =
|
|
72
|
+
const fhePublicKey = _deserializeTfhePublicKey(fhe);
|
|
64
73
|
const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
|
|
65
|
-
const zkCrs =
|
|
74
|
+
const zkCrs = _deserializeCompactPkeCrs(crs);
|
|
66
75
|
|
|
67
76
|
return { zkBuilder, zkCrs };
|
|
68
77
|
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type CofheClient } from '@/core';
|
|
2
|
+
import { arbSepolia as cofheArbSepolia } from '@/chains';
|
|
3
|
+
|
|
4
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
5
|
+
import { createCofheClient, createCofheConfig } from '../index.js';
|
|
6
|
+
|
|
7
|
+
describe('@cofhe/node - Client', () => {
|
|
8
|
+
let cofheClient: CofheClient;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
const config = createCofheConfig({
|
|
12
|
+
supportedChains: [cofheArbSepolia],
|
|
13
|
+
});
|
|
14
|
+
cofheClient = createCofheClient(config);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should automatically use filesystem storage as default', () => {
|
|
18
|
+
expect(cofheClient.config.fheKeyStorage).toBeDefined();
|
|
19
|
+
expect(cofheClient.config.fheKeyStorage).not.toBeNull();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should have the correct environment', () => {
|
|
23
|
+
expect(cofheClient.config.environment).toBe('node');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { arbSepolia } from '@/chains';
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect } from 'vitest';
|
|
4
|
+
import { createCofheConfig } from '../index.js';
|
|
5
|
+
|
|
6
|
+
describe('@cofhe/node - Config', () => {
|
|
7
|
+
it('should automatically inject filesystem storage as default', () => {
|
|
8
|
+
const config = createCofheConfig({
|
|
9
|
+
supportedChains: [arbSepolia],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
expect(config.fheKeyStorage).toBeDefined();
|
|
13
|
+
expect(config.fheKeyStorage).not.toBeNull();
|
|
14
|
+
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { Encryptable, FheTypes, type CofheClient } from '@/core';
|
|
2
|
+
import { arbSepolia as cofheArbSepolia, getChainById } from '@/chains';
|
|
3
|
+
import {
|
|
4
|
+
TEST_PRIVATE_KEY,
|
|
5
|
+
PRIMARY_TEST_CHAIN,
|
|
6
|
+
primaryTestChainRegistry,
|
|
7
|
+
isPrimaryTestChainReady,
|
|
8
|
+
} from '@cofhe/test-setup';
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
|
|
11
|
+
import type { Chain, PublicClient, WalletClient } from 'viem';
|
|
12
|
+
import { createPublicClient, createWalletClient, http } from 'viem';
|
|
13
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
14
|
+
import { arbitrumSepolia, baseSepolia, sepolia } from 'viem/chains';
|
|
15
|
+
import { createCofheClient, createCofheConfig } from '../index.js';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
|
|
18
|
+
const BOB_PRIVATE_KEY = (TEST_PRIVATE_KEY || DEFAULT_TEST_PRIVATE_KEY) as `0x${string}`;
|
|
19
|
+
const ALICE_PRIVATE_KEY = '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d';
|
|
20
|
+
|
|
21
|
+
const bobAccount = privateKeyToAccount(BOB_PRIVATE_KEY);
|
|
22
|
+
const aliceAccount = privateKeyToAccount(ALICE_PRIVATE_KEY);
|
|
23
|
+
|
|
24
|
+
const VIEM_CHAINS: Record<number, Chain> = {
|
|
25
|
+
421614: arbitrumSepolia,
|
|
26
|
+
84532: baseSepolia,
|
|
27
|
+
11155111: sepolia,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
describe('@cofhe/node - Inherited Client Tests', () => {
|
|
31
|
+
let cofheClient: CofheClient;
|
|
32
|
+
let publicClient: PublicClient;
|
|
33
|
+
let bobWalletClient: WalletClient;
|
|
34
|
+
let aliceWalletClient: WalletClient;
|
|
35
|
+
|
|
36
|
+
beforeAll(() => {
|
|
37
|
+
publicClient = createPublicClient({
|
|
38
|
+
chain: arbitrumSepolia,
|
|
39
|
+
transport: http(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
bobWalletClient = createWalletClient({
|
|
43
|
+
chain: arbitrumSepolia,
|
|
44
|
+
transport: http(),
|
|
45
|
+
account: bobAccount,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
aliceWalletClient = createWalletClient({
|
|
49
|
+
chain: arbitrumSepolia,
|
|
50
|
+
transport: http(),
|
|
51
|
+
account: aliceAccount,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
const config = createCofheConfig({
|
|
57
|
+
supportedChains: [cofheArbSepolia],
|
|
58
|
+
});
|
|
59
|
+
cofheClient = createCofheClient(config);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('Client Creation', () => {
|
|
63
|
+
it('should create a client with expected surface', () => {
|
|
64
|
+
expect(cofheClient).toBeDefined();
|
|
65
|
+
expect(cofheClient.config).toBeDefined();
|
|
66
|
+
expect(cofheClient.connected).toBe(false);
|
|
67
|
+
expect(typeof cofheClient.connect).toBe('function');
|
|
68
|
+
expect(typeof cofheClient.disconnect).toBe('function');
|
|
69
|
+
expect(typeof cofheClient.encryptInputs).toBe('function');
|
|
70
|
+
expect(typeof cofheClient.decryptForView).toBe('function');
|
|
71
|
+
expect(typeof cofheClient.decryptForTx).toBe('function');
|
|
72
|
+
expect(typeof cofheClient.getSnapshot).toBe('function');
|
|
73
|
+
expect(typeof cofheClient.subscribe).toBe('function');
|
|
74
|
+
expect(cofheClient.permits).toBeDefined();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('Connection', () => {
|
|
79
|
+
it('should connect to a real chain', async () => {
|
|
80
|
+
await cofheClient.connect(publicClient, bobWalletClient);
|
|
81
|
+
|
|
82
|
+
expect(cofheClient.connected).toBe(true);
|
|
83
|
+
|
|
84
|
+
const snapshot = cofheClient.getSnapshot();
|
|
85
|
+
expect(snapshot.connected).toBe(true);
|
|
86
|
+
expect(snapshot.chainId).toBe(cofheArbSepolia.id);
|
|
87
|
+
expect(snapshot.account).toBe(bobAccount.address);
|
|
88
|
+
}, 30000);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('Encrypt Input', () => {
|
|
92
|
+
it('should encrypt a uint128 value', async () => {
|
|
93
|
+
await cofheClient.connect(publicClient, bobWalletClient);
|
|
94
|
+
|
|
95
|
+
const encrypted = await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
96
|
+
|
|
97
|
+
expect(encrypted).toBeDefined();
|
|
98
|
+
expect(encrypted.length).toBe(1);
|
|
99
|
+
expect(encrypted[0].utype).toBe(FheTypes.Uint128);
|
|
100
|
+
expect(encrypted[0].ctHash).toBeDefined();
|
|
101
|
+
expect(typeof encrypted[0].ctHash).toBe('bigint');
|
|
102
|
+
expect(encrypted[0].signature).toBeDefined();
|
|
103
|
+
expect(typeof encrypted[0].signature).toBe('string');
|
|
104
|
+
expect(encrypted[0].securityZone).toBe(0);
|
|
105
|
+
}, 60000);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe('Self Permit', () => {
|
|
109
|
+
it('should create a self permit', async () => {
|
|
110
|
+
await cofheClient.connect(publicClient, bobWalletClient);
|
|
111
|
+
|
|
112
|
+
const permit = await cofheClient.permits.createSelf({
|
|
113
|
+
issuer: bobAccount.address,
|
|
114
|
+
name: 'Test Self Permit',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(permit).toBeDefined();
|
|
118
|
+
expect(permit.type).toBe('self');
|
|
119
|
+
expect(permit.name).toBe('Test Self Permit');
|
|
120
|
+
expect(permit.issuer).toBe(bobAccount.address);
|
|
121
|
+
expect(permit.issuerSignature).not.toBe('0x');
|
|
122
|
+
expect(permit.sealingPair).toBeDefined();
|
|
123
|
+
expect(permit.sealingPair.publicKey).toBeDefined();
|
|
124
|
+
|
|
125
|
+
const activePermit = cofheClient.permits.getActivePermit();
|
|
126
|
+
expect(activePermit).toBeDefined();
|
|
127
|
+
expect(activePermit!.hash).toBe(permit.hash);
|
|
128
|
+
}, 30000);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('Sharing Permit', () => {
|
|
132
|
+
it('should create a sharing permit, export it, and import it as another user', async () => {
|
|
133
|
+
await cofheClient.connect(publicClient, bobWalletClient);
|
|
134
|
+
|
|
135
|
+
const sharingPermit = await cofheClient.permits.createSharing({
|
|
136
|
+
issuer: bobAccount.address,
|
|
137
|
+
recipient: aliceAccount.address,
|
|
138
|
+
name: 'Test Sharing Permit',
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
expect(sharingPermit).toBeDefined();
|
|
142
|
+
expect(sharingPermit.type).toBe('sharing');
|
|
143
|
+
expect(sharingPermit.issuer).toBe(bobAccount.address);
|
|
144
|
+
expect(sharingPermit.recipient).toBe(aliceAccount.address);
|
|
145
|
+
expect(sharingPermit.issuerSignature).not.toBe('0x');
|
|
146
|
+
|
|
147
|
+
const exported = cofheClient.permits.export(sharingPermit);
|
|
148
|
+
expect(exported).toBeDefined();
|
|
149
|
+
const parsed = JSON.parse(exported);
|
|
150
|
+
expect(parsed.type).toBe('sharing');
|
|
151
|
+
expect(parsed.issuer).toBe(bobAccount.address);
|
|
152
|
+
expect(parsed.recipient).toBe(aliceAccount.address);
|
|
153
|
+
expect(parsed.issuerSignature).toBeDefined();
|
|
154
|
+
expect(parsed).not.toHaveProperty('sealingPair');
|
|
155
|
+
|
|
156
|
+
const aliceConfig = createCofheConfig({
|
|
157
|
+
supportedChains: [cofheArbSepolia],
|
|
158
|
+
});
|
|
159
|
+
const aliceClient = createCofheClient(aliceConfig);
|
|
160
|
+
await aliceClient.connect(publicClient, aliceWalletClient);
|
|
161
|
+
|
|
162
|
+
const importedPermit = await aliceClient.permits.importShared(exported);
|
|
163
|
+
|
|
164
|
+
expect(importedPermit).toBeDefined();
|
|
165
|
+
expect(importedPermit.type).toBe('recipient');
|
|
166
|
+
expect(importedPermit.issuer).toBe(bobAccount.address);
|
|
167
|
+
expect(importedPermit.recipient).toBe(aliceAccount.address);
|
|
168
|
+
expect(importedPermit.recipientSignature).not.toBe('0x');
|
|
169
|
+
expect(importedPermit.sealingPair).toBeDefined();
|
|
170
|
+
}, 30000);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('Decrypt (read-only, pre-stored values)', () => {
|
|
174
|
+
let decryptClient: CofheClient;
|
|
175
|
+
let decryptPublicClient: PublicClient;
|
|
176
|
+
let decryptWalletClient: WalletClient;
|
|
177
|
+
|
|
178
|
+
let privateCtHash: `0x${string}`;
|
|
179
|
+
let privateValue: bigint;
|
|
180
|
+
let publicCtHash: `0x${string}`;
|
|
181
|
+
let publicValue: bigint;
|
|
182
|
+
|
|
183
|
+
beforeAll(() => {
|
|
184
|
+
if (!isPrimaryTestChainReady(primaryTestChainRegistry)) {
|
|
185
|
+
throw new Error('Primary test chain registry not initialized. Run `pnpm test:setup` first.');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const reg = primaryTestChainRegistry;
|
|
189
|
+
const viemChain = VIEM_CHAINS[reg.chainId];
|
|
190
|
+
if (!viemChain) throw new Error(`No viem chain mapping for chain ${reg.chainId}`);
|
|
191
|
+
|
|
192
|
+
const cofheChain = getChainById(reg.chainId);
|
|
193
|
+
if (!cofheChain) throw new Error(`No cofhe chain config for chain ${reg.chainId}`);
|
|
194
|
+
|
|
195
|
+
privateCtHash = reg.privateValue.ctHash as `0x${string}`;
|
|
196
|
+
privateValue = BigInt(reg.privateValue.value);
|
|
197
|
+
publicCtHash = reg.publicValue.ctHash as `0x${string}`;
|
|
198
|
+
publicValue = BigInt(reg.publicValue.value);
|
|
199
|
+
|
|
200
|
+
decryptPublicClient = createPublicClient({ chain: viemChain, transport: http() });
|
|
201
|
+
decryptWalletClient = createWalletClient({ chain: viemChain, transport: http(), account: bobAccount });
|
|
202
|
+
|
|
203
|
+
const config = createCofheConfig({ supportedChains: [cofheChain] });
|
|
204
|
+
decryptClient = createCofheClient(config);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('decryptForView — private value with permit', async () => {
|
|
208
|
+
await decryptClient.connect(decryptPublicClient, decryptWalletClient);
|
|
209
|
+
|
|
210
|
+
await decryptClient.permits.createSelf({
|
|
211
|
+
issuer: bobAccount.address,
|
|
212
|
+
name: 'Decrypt View Permit',
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
const result = await decryptClient.decryptForView(privateCtHash, FheTypes.Uint32).execute();
|
|
216
|
+
expect(result).toBe(privateValue);
|
|
217
|
+
}, 180000);
|
|
218
|
+
|
|
219
|
+
it('decryptForTx — public value without permit', async () => {
|
|
220
|
+
await decryptClient.connect(decryptPublicClient, decryptWalletClient);
|
|
221
|
+
|
|
222
|
+
const result = await decryptClient.decryptForTx(publicCtHash).withoutPermit().execute();
|
|
223
|
+
|
|
224
|
+
expect(BigInt(result.ctHash)).toBe(BigInt(publicCtHash));
|
|
225
|
+
expect(result.decryptedValue).toBe(publicValue);
|
|
226
|
+
expect(result.signature).toMatch(/^0x[0-9a-fA-F]+$/);
|
|
227
|
+
}, 180000);
|
|
228
|
+
|
|
229
|
+
it('decryptForTx — private value with permit', async () => {
|
|
230
|
+
await decryptClient.connect(decryptPublicClient, decryptWalletClient);
|
|
231
|
+
|
|
232
|
+
const permit = await decryptClient.permits.createSelf({
|
|
233
|
+
issuer: bobAccount.address,
|
|
234
|
+
name: 'Decrypt Tx Permit',
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const result = await decryptClient.decryptForTx(privateCtHash).withPermit(permit).execute();
|
|
238
|
+
|
|
239
|
+
expect(BigInt(result.ctHash)).toBe(BigInt(privateCtHash));
|
|
240
|
+
expect(result.decryptedValue).toBe(privateValue);
|
|
241
|
+
expect(result.signature).toBeDefined();
|
|
242
|
+
}, 180000);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Encryptable, type CofheClient } from '@/core';
|
|
2
|
+
import { arbSepolia as cofheArbSepolia } from '@/chains';
|
|
3
|
+
|
|
4
|
+
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
|
|
5
|
+
import type { PublicClient, WalletClient } from 'viem';
|
|
6
|
+
import { createPublicClient, createWalletClient, http } from 'viem';
|
|
7
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
8
|
+
import { arbitrumSepolia as viemArbitrumSepolia } from 'viem/chains';
|
|
9
|
+
import { createCofheClient, createCofheConfig } from '../index.js';
|
|
10
|
+
|
|
11
|
+
const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
|
|
12
|
+
|
|
13
|
+
describe('@cofhe/node - TFHE Initialization Tests', () => {
|
|
14
|
+
let cofheClient: CofheClient;
|
|
15
|
+
let publicClient: PublicClient;
|
|
16
|
+
let walletClient: WalletClient;
|
|
17
|
+
|
|
18
|
+
beforeAll(() => {
|
|
19
|
+
publicClient = createPublicClient({
|
|
20
|
+
chain: viemArbitrumSepolia,
|
|
21
|
+
transport: http(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const account = privateKeyToAccount(TEST_PRIVATE_KEY);
|
|
25
|
+
walletClient = createWalletClient({
|
|
26
|
+
chain: viemArbitrumSepolia,
|
|
27
|
+
transport: http(),
|
|
28
|
+
account,
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
const config = createCofheConfig({
|
|
34
|
+
supportedChains: [cofheArbSepolia],
|
|
35
|
+
});
|
|
36
|
+
cofheClient = createCofheClient(config);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('Node TFHE Initialization', () => {
|
|
40
|
+
it('should initialize node-tfhe on first encryption', async () => {
|
|
41
|
+
await cofheClient.connect(publicClient, walletClient);
|
|
42
|
+
|
|
43
|
+
const result = await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
44
|
+
|
|
45
|
+
expect(result).toBeDefined();
|
|
46
|
+
}, 60000);
|
|
47
|
+
|
|
48
|
+
it('should handle multiple encryptions without re-initializing', async () => {
|
|
49
|
+
await cofheClient.connect(publicClient, walletClient);
|
|
50
|
+
|
|
51
|
+
await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
52
|
+
|
|
53
|
+
await cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute();
|
|
54
|
+
}, 120000);
|
|
55
|
+
});
|
|
56
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cofhe/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SDK for Fhenix COFHE coprocessor interaction",
|
|
6
6
|
"main": "./dist/core.cjs",
|
|
@@ -57,14 +57,14 @@
|
|
|
57
57
|
"CHANGELOG.md"
|
|
58
58
|
],
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"iframe-shared-storage": "
|
|
61
|
-
"immer": "
|
|
62
|
-
"node-tfhe": "
|
|
63
|
-
"tfhe": "
|
|
64
|
-
"tweetnacl": "
|
|
65
|
-
"viem": "
|
|
66
|
-
"zod": "
|
|
67
|
-
"zustand": "
|
|
60
|
+
"iframe-shared-storage": "1.0.34",
|
|
61
|
+
"immer": "10.1.1",
|
|
62
|
+
"node-tfhe": "1.5.3",
|
|
63
|
+
"tfhe": "1.5.3",
|
|
64
|
+
"tweetnacl": "1.0.3",
|
|
65
|
+
"viem": "2.38.6",
|
|
66
|
+
"zod": "4.0.0",
|
|
67
|
+
"zustand": "5.0.1"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"@nomicfoundation/hardhat-ethers": "^3.0.0",
|
|
@@ -88,24 +88,26 @@
|
|
|
88
88
|
}
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
|
-
"@nomicfoundation/hardhat-ethers": "
|
|
92
|
-
"@types/node": "
|
|
93
|
-
"@vitest/browser": "
|
|
94
|
-
"@vitest/coverage-v8": "
|
|
95
|
-
"eslint": "
|
|
96
|
-
"ethers5": "npm:ethers
|
|
97
|
-
"ethers6": "npm:ethers
|
|
98
|
-
"happy-dom": "
|
|
99
|
-
"hardhat": "
|
|
100
|
-
"playwright": "
|
|
101
|
-
"tsup": "
|
|
91
|
+
"@nomicfoundation/hardhat-ethers": "3.1.0",
|
|
92
|
+
"@types/node": "20.19.15",
|
|
93
|
+
"@vitest/browser": "3.2.4",
|
|
94
|
+
"@vitest/coverage-v8": "3.2.4",
|
|
95
|
+
"eslint": "8.57.1",
|
|
96
|
+
"ethers5": "npm:ethers@5.8.0",
|
|
97
|
+
"ethers6": "npm:ethers@6.15.0",
|
|
98
|
+
"happy-dom": "15.11.7",
|
|
99
|
+
"hardhat": "2.26.3",
|
|
100
|
+
"playwright": "1.55.0",
|
|
101
|
+
"tsup": "8.0.2",
|
|
102
102
|
"typescript": "5.5.4",
|
|
103
|
-
"vitest": "
|
|
103
|
+
"vitest": "3.2.4",
|
|
104
|
+
"@cofhe/test-setup": "0.0.0",
|
|
104
105
|
"@cofhe/eslint-config": "0.2.1",
|
|
105
106
|
"@cofhe/tsconfig": "0.1.2"
|
|
106
107
|
},
|
|
107
108
|
"publishConfig": {
|
|
108
|
-
"access": "public"
|
|
109
|
+
"access": "public",
|
|
110
|
+
"registry": "https://registry.npmjs.org/"
|
|
109
111
|
},
|
|
110
112
|
"scripts": {
|
|
111
113
|
"build": "tsup",
|