@cofhe/sdk 0.1.1 → 0.2.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 +14 -0
- package/adapters/ethers6.ts +28 -28
- package/adapters/hardhat.ts +0 -1
- package/adapters/index.test.ts +14 -19
- package/adapters/smartWallet.ts +81 -73
- package/adapters/test-utils.ts +45 -45
- package/adapters/types.ts +3 -3
- package/chains/chains/localcofhe.ts +14 -0
- package/chains/chains.test.ts +2 -1
- package/chains/index.ts +3 -1
- package/core/baseBuilder.ts +30 -49
- package/core/client.test.ts +94 -77
- package/core/client.ts +133 -149
- package/core/clientTypes.ts +108 -0
- package/core/config.test.ts +22 -11
- package/core/config.ts +16 -9
- package/core/decrypt/decryptHandleBuilder.ts +51 -45
- package/core/decrypt/{tnSealOutput.ts → tnSealOutputV1.ts} +1 -1
- package/core/decrypt/tnSealOutputV2.ts +298 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +16 -10
- package/core/encrypt/encryptInputsBuilder.test.ts +132 -116
- package/core/encrypt/encryptInputsBuilder.ts +159 -111
- package/core/encrypt/encryptUtils.ts +6 -3
- package/core/encrypt/zkPackProveVerify.ts +70 -8
- package/core/error.ts +0 -2
- package/core/fetchKeys.test.ts +1 -18
- package/core/fetchKeys.ts +0 -26
- package/core/index.ts +29 -17
- package/core/keyStore.ts +65 -38
- package/core/permits.test.ts +253 -1
- package/core/permits.ts +80 -16
- package/core/types.ts +198 -152
- package/core/utils.ts +43 -1
- package/dist/adapters.d.cts +38 -20
- package/dist/adapters.d.ts +38 -20
- package/dist/chains.cjs +14 -1
- package/dist/chains.d.cts +23 -1
- package/dist/chains.d.ts +23 -1
- package/dist/chains.js +1 -1
- package/dist/{chunk-LU7BMUUT.js → chunk-UGBVZNRT.js} +39 -25
- package/dist/{chunk-GZCQQYVI.js → chunk-WEAZ25JO.js} +14 -2
- package/dist/{chunk-KFGPTJ6X.js → chunk-WGCRJCBR.js} +1920 -1692
- package/dist/{types-bB7wLj0q.d.cts → clientTypes-5_1nwtUe.d.cts} +308 -347
- package/dist/{types-PhwGgQvs.d.ts → clientTypes-Es7fyi65.d.ts} +308 -347
- package/dist/core.cjs +2872 -2632
- package/dist/core.d.cts +101 -6
- package/dist/core.d.ts +101 -6
- package/dist/core.js +3 -3
- package/dist/node.cjs +2716 -2520
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +4 -3
- package/dist/{permit-S9CnI6MF.d.cts → permit-fUSe6KKq.d.cts} +31 -15
- package/dist/{permit-S9CnI6MF.d.ts → permit-fUSe6KKq.d.ts} +31 -15
- package/dist/permits.cjs +39 -24
- package/dist/permits.d.cts +137 -148
- package/dist/permits.d.ts +137 -148
- package/dist/permits.js +1 -1
- package/dist/web.cjs +2929 -2518
- package/dist/web.d.cts +21 -5
- package/dist/web.d.ts +21 -5
- package/dist/web.js +185 -9
- package/dist/zkProve.worker.cjs +93 -0
- package/dist/zkProve.worker.d.cts +2 -0
- package/dist/zkProve.worker.d.ts +2 -0
- package/dist/zkProve.worker.js +91 -0
- package/node/client.test.ts +20 -25
- package/node/encryptInputs.test.ts +18 -38
- package/node/index.ts +1 -0
- package/package.json +14 -14
- package/permits/index.ts +1 -0
- package/permits/localstorage.test.ts +0 -1
- package/permits/permit.test.ts +25 -22
- package/permits/permit.ts +30 -21
- package/permits/sealing.test.ts +3 -3
- package/permits/sealing.ts +2 -2
- package/permits/store.ts +5 -7
- package/permits/test-utils.ts +1 -1
- package/permits/types.ts +17 -0
- package/permits/utils.ts +0 -1
- package/permits/validation.ts +24 -4
- package/web/client.web.test.ts +20 -25
- package/web/config.web.test.ts +0 -2
- package/web/encryptInputs.web.test.ts +31 -54
- package/web/index.ts +65 -1
- package/web/storage.ts +19 -5
- package/web/worker.builder.web.test.ts +148 -0
- package/web/worker.config.web.test.ts +329 -0
- package/web/worker.output.web.test.ts +84 -0
- package/web/workerManager.test.ts +80 -0
- package/web/workerManager.ts +214 -0
- package/web/workerManager.web.test.ts +114 -0
- package/web/zkProve.worker.ts +133 -0
- package/core/result.test.ts +0 -180
- package/core/result.ts +0 -67
- package/core/test-utils.ts +0 -45
package/dist/web.d.cts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import './permit-S9CnI6MF.cjs';
|
|
3
|
-
import 'zod';
|
|
1
|
+
import { C as CofhesdkInputConfig, a as CofhesdkConfig, b as CofhesdkClient, E as EncryptableItem } from './clientTypes-5_1nwtUe.cjs';
|
|
4
2
|
import 'viem';
|
|
5
3
|
import './types-KImPrEIe.cjs';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './permit-fUSe6KKq.cjs';
|
|
6
6
|
import 'zustand/vanilla';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Terminate the worker
|
|
10
|
+
*/
|
|
11
|
+
declare function terminateWorker(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Check if workers are available
|
|
14
|
+
*/
|
|
15
|
+
declare function areWorkersAvailable(): boolean;
|
|
16
|
+
|
|
8
17
|
/**
|
|
9
18
|
* Creates a CoFHE SDK configuration for web with IndexedDB storage as default
|
|
10
19
|
* @param config - The CoFHE SDK input configuration (fheKeyStorage will default to IndexedDB if not provided)
|
|
@@ -14,9 +23,16 @@ declare function createCofhesdkConfig(config: CofhesdkInputConfig): CofhesdkConf
|
|
|
14
23
|
/**
|
|
15
24
|
* Creates a CoFHE SDK client instance for web with TFHE automatically configured
|
|
16
25
|
* TFHE will be initialized automatically on first encryption - no manual setup required
|
|
26
|
+
* Workers are automatically enabled if available (can be disabled via config.useWorkers)
|
|
17
27
|
* @param config - The CoFHE SDK configuration (use createCofhesdkConfig to create with web defaults)
|
|
18
28
|
* @returns The CoFHE SDK client instance
|
|
19
29
|
*/
|
|
20
|
-
declare function createCofhesdkClient(config:
|
|
30
|
+
declare function createCofhesdkClient<TConfig extends CofhesdkConfig>(config: TConfig): CofhesdkClient<TConfig>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Test helper: Create a client with custom worker function (for testing fallback behavior)
|
|
34
|
+
* @internal - Only for testing purposes
|
|
35
|
+
*/
|
|
36
|
+
declare function createCofhesdkClientWithCustomWorker(config: CofhesdkConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofhesdkClient;
|
|
21
37
|
|
|
22
|
-
export { createCofhesdkClient, createCofhesdkConfig };
|
|
38
|
+
export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, terminateWorker };
|
package/dist/web.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import './permit-S9CnI6MF.js';
|
|
3
|
-
import 'zod';
|
|
1
|
+
import { C as CofhesdkInputConfig, a as CofhesdkConfig, b as CofhesdkClient, E as EncryptableItem } from './clientTypes-Es7fyi65.js';
|
|
4
2
|
import 'viem';
|
|
5
3
|
import './types-KImPrEIe.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import './permit-fUSe6KKq.js';
|
|
6
6
|
import 'zustand/vanilla';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Terminate the worker
|
|
10
|
+
*/
|
|
11
|
+
declare function terminateWorker(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Check if workers are available
|
|
14
|
+
*/
|
|
15
|
+
declare function areWorkersAvailable(): boolean;
|
|
16
|
+
|
|
8
17
|
/**
|
|
9
18
|
* Creates a CoFHE SDK configuration for web with IndexedDB storage as default
|
|
10
19
|
* @param config - The CoFHE SDK input configuration (fheKeyStorage will default to IndexedDB if not provided)
|
|
@@ -14,9 +23,16 @@ declare function createCofhesdkConfig(config: CofhesdkInputConfig): CofhesdkConf
|
|
|
14
23
|
/**
|
|
15
24
|
* Creates a CoFHE SDK client instance for web with TFHE automatically configured
|
|
16
25
|
* TFHE will be initialized automatically on first encryption - no manual setup required
|
|
26
|
+
* Workers are automatically enabled if available (can be disabled via config.useWorkers)
|
|
17
27
|
* @param config - The CoFHE SDK configuration (use createCofhesdkConfig to create with web defaults)
|
|
18
28
|
* @returns The CoFHE SDK client instance
|
|
19
29
|
*/
|
|
20
|
-
declare function createCofhesdkClient(config:
|
|
30
|
+
declare function createCofhesdkClient<TConfig extends CofhesdkConfig>(config: TConfig): CofhesdkClient<TConfig>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Test helper: Create a client with custom worker function (for testing fallback behavior)
|
|
34
|
+
* @internal - Only for testing purposes
|
|
35
|
+
*/
|
|
36
|
+
declare function createCofhesdkClientWithCustomWorker(config: CofhesdkConfig, customZkProveWorkerFn: (fheKeyHex: string, crsHex: string, items: EncryptableItem[], metadata: Uint8Array) => Promise<Uint8Array>): CofhesdkClient;
|
|
21
37
|
|
|
22
|
-
export { createCofhesdkClient, createCofhesdkConfig };
|
|
38
|
+
export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, terminateWorker };
|
package/dist/web.js
CHANGED
|
@@ -1,22 +1,176 @@
|
|
|
1
|
-
import { createCofhesdkConfigBase, createCofhesdkClientBase } from './chunk-
|
|
2
|
-
import './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import {
|
|
1
|
+
import { createCofhesdkConfigBase, createCofhesdkClientBase, fheTypeToString } from './chunk-WGCRJCBR.js';
|
|
2
|
+
import './chunk-WEAZ25JO.js';
|
|
3
|
+
import './chunk-UGBVZNRT.js';
|
|
4
|
+
import { constructClient } from 'iframe-shared-storage';
|
|
5
5
|
import init, { init_panic_hook, TfheCompactPublicKey, CompactPkeCrs, ProvenCompactCiphertextList } from 'tfhe';
|
|
6
6
|
|
|
7
7
|
var createWebStorage = () => {
|
|
8
|
+
const client = constructClient({
|
|
9
|
+
iframe: {
|
|
10
|
+
src: "https://iframe-shared-storage.vercel.app/hub.html",
|
|
11
|
+
messagingOptions: {
|
|
12
|
+
enableLog: "both"
|
|
13
|
+
},
|
|
14
|
+
iframeReadyTimeoutMs: 3e4,
|
|
15
|
+
// if the iframe is not initied during this interval AND a reuqest is made, such request will throw an error
|
|
16
|
+
methodCallTimeoutMs: 1e4,
|
|
17
|
+
// if a method call is not answered during this interval, the call will throw an error
|
|
18
|
+
methodCallRetries: 3
|
|
19
|
+
// number of retries for a method call if it times out
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const indexedDBKeyval = client.indexedDBKeyval;
|
|
8
23
|
return {
|
|
9
24
|
getItem: async (name) => {
|
|
10
|
-
return await get(name)
|
|
25
|
+
return await indexedDBKeyval.get(name) ?? null;
|
|
11
26
|
},
|
|
12
27
|
setItem: async (name, value) => {
|
|
13
|
-
await set(name, value);
|
|
28
|
+
await indexedDBKeyval.set(name, value);
|
|
14
29
|
},
|
|
15
30
|
removeItem: async (name) => {
|
|
16
|
-
await del(name);
|
|
31
|
+
await indexedDBKeyval.del(name);
|
|
17
32
|
}
|
|
18
33
|
};
|
|
19
34
|
};
|
|
35
|
+
|
|
36
|
+
// web/workerManager.ts
|
|
37
|
+
var ZkProveWorkerManager = class {
|
|
38
|
+
worker = null;
|
|
39
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
40
|
+
requestCounter = 0;
|
|
41
|
+
workerReady = false;
|
|
42
|
+
initializationPromise = null;
|
|
43
|
+
/**
|
|
44
|
+
* Initialize the worker
|
|
45
|
+
*/
|
|
46
|
+
async initializeWorker() {
|
|
47
|
+
if (this.worker && this.workerReady) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (this.initializationPromise) {
|
|
51
|
+
return this.initializationPromise;
|
|
52
|
+
}
|
|
53
|
+
this.initializationPromise = new Promise((resolve, reject) => {
|
|
54
|
+
try {
|
|
55
|
+
if (typeof Worker === "undefined") {
|
|
56
|
+
reject(new Error("Web Workers not supported"));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
this.worker = new Worker(new URL("./zkProve.worker.js", import.meta.url), { type: "module" });
|
|
61
|
+
} catch (error) {
|
|
62
|
+
reject(new Error(`Failed to create worker: ${error}`));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.worker.onmessage = (event) => {
|
|
66
|
+
const { id, type, result, error } = event.data;
|
|
67
|
+
if (type === "ready") {
|
|
68
|
+
this.workerReady = true;
|
|
69
|
+
resolve();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const pending = this.pendingRequests.get(id);
|
|
73
|
+
if (!pending) {
|
|
74
|
+
console.warn("[Worker Manager] Received response for unknown request:", id);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
clearTimeout(pending.timeoutId);
|
|
78
|
+
this.pendingRequests.delete(id);
|
|
79
|
+
if (type === "success" && result) {
|
|
80
|
+
pending.resolve(new Uint8Array(result));
|
|
81
|
+
} else if (type === "error") {
|
|
82
|
+
pending.reject(new Error(error || "Worker error"));
|
|
83
|
+
} else {
|
|
84
|
+
pending.reject(new Error("Invalid response from worker"));
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
this.worker.onerror = (error) => {
|
|
88
|
+
console.error("[Worker Manager] Worker error event:", error);
|
|
89
|
+
console.error("[Worker Manager] Error message:", error.message);
|
|
90
|
+
console.error("[Worker Manager] Error filename:", error.filename);
|
|
91
|
+
console.error("[Worker Manager] Error lineno:", error.lineno);
|
|
92
|
+
if (!this.workerReady) {
|
|
93
|
+
reject(new Error(`Worker failed to initialize: ${error.message || "Unknown error"}`));
|
|
94
|
+
}
|
|
95
|
+
this.pendingRequests.forEach(({ reject: reject2, timeoutId }) => {
|
|
96
|
+
clearTimeout(timeoutId);
|
|
97
|
+
reject2(new Error("Worker encountered an error"));
|
|
98
|
+
});
|
|
99
|
+
this.pendingRequests.clear();
|
|
100
|
+
};
|
|
101
|
+
setTimeout(() => {
|
|
102
|
+
if (!this.workerReady) {
|
|
103
|
+
reject(new Error("Worker initialization timeout"));
|
|
104
|
+
}
|
|
105
|
+
}, 5e3);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
reject(error);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
return this.initializationPromise;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Submit a proof generation request to the worker
|
|
114
|
+
*/
|
|
115
|
+
async submitProof(fheKeyHex, crsHex, items, metadata) {
|
|
116
|
+
await this.initializeWorker();
|
|
117
|
+
const id = `zkprove-${Date.now()}-${this.requestCounter++}`;
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
const timeoutId = setTimeout(() => {
|
|
120
|
+
this.pendingRequests.delete(id);
|
|
121
|
+
reject(new Error("Worker request timeout (30s)"));
|
|
122
|
+
}, 3e4);
|
|
123
|
+
this.pendingRequests.set(id, { resolve, reject, timeoutId });
|
|
124
|
+
const message = {
|
|
125
|
+
id,
|
|
126
|
+
type: "zkProve",
|
|
127
|
+
fheKeyHex,
|
|
128
|
+
crsHex,
|
|
129
|
+
items,
|
|
130
|
+
metadata: Array.from(metadata)
|
|
131
|
+
};
|
|
132
|
+
this.worker.postMessage(message);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Terminate the worker and clean up
|
|
137
|
+
*/
|
|
138
|
+
terminate() {
|
|
139
|
+
if (this.worker) {
|
|
140
|
+
this.worker.terminate();
|
|
141
|
+
this.worker = null;
|
|
142
|
+
this.workerReady = false;
|
|
143
|
+
this.initializationPromise = null;
|
|
144
|
+
}
|
|
145
|
+
this.pendingRequests.forEach(({ reject, timeoutId }) => {
|
|
146
|
+
clearTimeout(timeoutId);
|
|
147
|
+
reject(new Error("Worker terminated"));
|
|
148
|
+
});
|
|
149
|
+
this.pendingRequests.clear();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check if worker is available
|
|
153
|
+
*/
|
|
154
|
+
isAvailable() {
|
|
155
|
+
return typeof Worker !== "undefined";
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
var workerManager = null;
|
|
159
|
+
function getWorkerManager() {
|
|
160
|
+
if (!workerManager) {
|
|
161
|
+
workerManager = new ZkProveWorkerManager();
|
|
162
|
+
}
|
|
163
|
+
return workerManager;
|
|
164
|
+
}
|
|
165
|
+
function terminateWorker() {
|
|
166
|
+
if (workerManager) {
|
|
167
|
+
workerManager.terminate();
|
|
168
|
+
workerManager = null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function areWorkersAvailable() {
|
|
172
|
+
return typeof Worker !== "undefined";
|
|
173
|
+
}
|
|
20
174
|
var tfheInitialized = false;
|
|
21
175
|
async function initTfhe() {
|
|
22
176
|
if (tfheInitialized)
|
|
@@ -45,8 +199,17 @@ var zkBuilderAndCrsGenerator = (fhe, crs) => {
|
|
|
45
199
|
const zkCrs = CompactPkeCrs.deserialize(fromHexString(crs));
|
|
46
200
|
return { zkBuilder, zkCrs };
|
|
47
201
|
};
|
|
202
|
+
async function zkProveWithWorker(fheKeyHex, crsHex, items, metadata) {
|
|
203
|
+
const serializedItems = items.map((item) => ({
|
|
204
|
+
utype: fheTypeToString(item.utype),
|
|
205
|
+
data: typeof item.data === "bigint" ? item.data.toString() : item.data
|
|
206
|
+
}));
|
|
207
|
+
const workerManager2 = getWorkerManager();
|
|
208
|
+
return await workerManager2.submitProof(fheKeyHex, crsHex, serializedItems, metadata);
|
|
209
|
+
}
|
|
48
210
|
function createCofhesdkConfig(config) {
|
|
49
211
|
return createCofhesdkConfigBase({
|
|
212
|
+
environment: "web",
|
|
50
213
|
...config,
|
|
51
214
|
fheKeyStorage: config.fheKeyStorage === null ? null : config.fheKeyStorage ?? createWebStorage()
|
|
52
215
|
});
|
|
@@ -57,8 +220,21 @@ function createCofhesdkClient(config) {
|
|
|
57
220
|
zkBuilderAndCrsGenerator,
|
|
58
221
|
tfhePublicKeyDeserializer,
|
|
59
222
|
compactPkeCrsDeserializer,
|
|
60
|
-
initTfhe
|
|
223
|
+
initTfhe,
|
|
224
|
+
// Always provide the worker function if available - config.useWorkers controls usage
|
|
225
|
+
// areWorkersAvailable will return true if the Worker API is available and false in Node.js
|
|
226
|
+
zkProveWorkerFn: areWorkersAvailable() ? zkProveWithWorker : void 0
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
function createCofhesdkClientWithCustomWorker(config, customZkProveWorkerFn) {
|
|
230
|
+
return createCofhesdkClientBase({
|
|
231
|
+
config,
|
|
232
|
+
zkBuilderAndCrsGenerator,
|
|
233
|
+
tfhePublicKeyDeserializer,
|
|
234
|
+
compactPkeCrsDeserializer,
|
|
235
|
+
initTfhe,
|
|
236
|
+
zkProveWorkerFn: customZkProveWorkerFn
|
|
61
237
|
});
|
|
62
238
|
}
|
|
63
239
|
|
|
64
|
-
export { createCofhesdkClient, createCofhesdkConfig };
|
|
240
|
+
export { areWorkersAvailable, createCofhesdkClient, createCofhesdkClientWithCustomWorker, createCofhesdkConfig, terminateWorker };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// web/zkProve.worker.ts
|
|
4
|
+
var tfheModule = null;
|
|
5
|
+
var initialized = false;
|
|
6
|
+
async function initTfhe() {
|
|
7
|
+
if (initialized)
|
|
8
|
+
return;
|
|
9
|
+
try {
|
|
10
|
+
tfheModule = await import('tfhe');
|
|
11
|
+
await tfheModule.default();
|
|
12
|
+
await tfheModule.init_panic_hook();
|
|
13
|
+
initialized = true;
|
|
14
|
+
console.log("[Worker] TFHE initialized");
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error("[Worker] Failed to initialize TFHE:", error);
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function fromHexString(hexString) {
|
|
21
|
+
const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
|
|
22
|
+
const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
|
|
23
|
+
if (!arr)
|
|
24
|
+
return new Uint8Array();
|
|
25
|
+
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
26
|
+
}
|
|
27
|
+
self.onmessage = async (event) => {
|
|
28
|
+
const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
|
|
29
|
+
if (type !== "zkProve") {
|
|
30
|
+
self.postMessage({
|
|
31
|
+
id,
|
|
32
|
+
type: "error",
|
|
33
|
+
error: "Invalid message type"
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
await initTfhe();
|
|
39
|
+
if (!tfheModule) {
|
|
40
|
+
throw new Error("TFHE module not initialized");
|
|
41
|
+
}
|
|
42
|
+
const fheKeyBytes = fromHexString(fheKeyHex);
|
|
43
|
+
const crsBytes = fromHexString(crsHex);
|
|
44
|
+
const fheKey = tfheModule.TfheCompactPublicKey.deserialize(fheKeyBytes);
|
|
45
|
+
const crs = tfheModule.CompactPkeCrs.deserialize(crsBytes);
|
|
46
|
+
const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
|
|
47
|
+
for (const item of items) {
|
|
48
|
+
switch (item.utype) {
|
|
49
|
+
case "bool":
|
|
50
|
+
builder.push_boolean(Boolean(item.data));
|
|
51
|
+
break;
|
|
52
|
+
case "uint8":
|
|
53
|
+
builder.push_u8(Number(item.data));
|
|
54
|
+
break;
|
|
55
|
+
case "uint16":
|
|
56
|
+
builder.push_u16(Number(item.data));
|
|
57
|
+
break;
|
|
58
|
+
case "uint32":
|
|
59
|
+
builder.push_u32(Number(item.data));
|
|
60
|
+
break;
|
|
61
|
+
case "uint64":
|
|
62
|
+
builder.push_u64(BigInt(item.data));
|
|
63
|
+
break;
|
|
64
|
+
case "uint128":
|
|
65
|
+
builder.push_u128(BigInt(item.data));
|
|
66
|
+
break;
|
|
67
|
+
case "uint160":
|
|
68
|
+
builder.push_u160(BigInt(item.data));
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
throw new Error(`Unsupported type: ${item.utype}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const metadataBytes = new Uint8Array(metadata);
|
|
75
|
+
const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
|
|
76
|
+
const result = compactList.serialize();
|
|
77
|
+
self.postMessage({
|
|
78
|
+
id,
|
|
79
|
+
type: "success",
|
|
80
|
+
result: Array.from(result)
|
|
81
|
+
});
|
|
82
|
+
} catch (error) {
|
|
83
|
+
self.postMessage({
|
|
84
|
+
id,
|
|
85
|
+
type: "error",
|
|
86
|
+
error: error instanceof Error ? error.message : String(error)
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
self.postMessage({
|
|
91
|
+
id: "init",
|
|
92
|
+
type: "ready"
|
|
93
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// web/zkProve.worker.ts
|
|
2
|
+
var tfheModule = null;
|
|
3
|
+
var initialized = false;
|
|
4
|
+
async function initTfhe() {
|
|
5
|
+
if (initialized)
|
|
6
|
+
return;
|
|
7
|
+
try {
|
|
8
|
+
tfheModule = await import('tfhe');
|
|
9
|
+
await tfheModule.default();
|
|
10
|
+
await tfheModule.init_panic_hook();
|
|
11
|
+
initialized = true;
|
|
12
|
+
console.log("[Worker] TFHE initialized");
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error("[Worker] Failed to initialize TFHE:", error);
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function fromHexString(hexString) {
|
|
19
|
+
const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
|
|
20
|
+
const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
|
|
21
|
+
if (!arr)
|
|
22
|
+
return new Uint8Array();
|
|
23
|
+
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
24
|
+
}
|
|
25
|
+
self.onmessage = async (event) => {
|
|
26
|
+
const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
|
|
27
|
+
if (type !== "zkProve") {
|
|
28
|
+
self.postMessage({
|
|
29
|
+
id,
|
|
30
|
+
type: "error",
|
|
31
|
+
error: "Invalid message type"
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
await initTfhe();
|
|
37
|
+
if (!tfheModule) {
|
|
38
|
+
throw new Error("TFHE module not initialized");
|
|
39
|
+
}
|
|
40
|
+
const fheKeyBytes = fromHexString(fheKeyHex);
|
|
41
|
+
const crsBytes = fromHexString(crsHex);
|
|
42
|
+
const fheKey = tfheModule.TfheCompactPublicKey.deserialize(fheKeyBytes);
|
|
43
|
+
const crs = tfheModule.CompactPkeCrs.deserialize(crsBytes);
|
|
44
|
+
const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
|
|
45
|
+
for (const item of items) {
|
|
46
|
+
switch (item.utype) {
|
|
47
|
+
case "bool":
|
|
48
|
+
builder.push_boolean(Boolean(item.data));
|
|
49
|
+
break;
|
|
50
|
+
case "uint8":
|
|
51
|
+
builder.push_u8(Number(item.data));
|
|
52
|
+
break;
|
|
53
|
+
case "uint16":
|
|
54
|
+
builder.push_u16(Number(item.data));
|
|
55
|
+
break;
|
|
56
|
+
case "uint32":
|
|
57
|
+
builder.push_u32(Number(item.data));
|
|
58
|
+
break;
|
|
59
|
+
case "uint64":
|
|
60
|
+
builder.push_u64(BigInt(item.data));
|
|
61
|
+
break;
|
|
62
|
+
case "uint128":
|
|
63
|
+
builder.push_u128(BigInt(item.data));
|
|
64
|
+
break;
|
|
65
|
+
case "uint160":
|
|
66
|
+
builder.push_u160(BigInt(item.data));
|
|
67
|
+
break;
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(`Unsupported type: ${item.utype}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const metadataBytes = new Uint8Array(metadata);
|
|
73
|
+
const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
|
|
74
|
+
const result = compactList.serialize();
|
|
75
|
+
self.postMessage({
|
|
76
|
+
id,
|
|
77
|
+
type: "success",
|
|
78
|
+
result: Array.from(result)
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
self.postMessage({
|
|
82
|
+
id,
|
|
83
|
+
type: "error",
|
|
84
|
+
error: error instanceof Error ? error.message : String(error)
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
self.postMessage({
|
|
89
|
+
id: "init",
|
|
90
|
+
type: "ready"
|
|
91
|
+
});
|
package/node/client.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CofhesdkClient } from '@/core';
|
|
1
|
+
import { type CofhesdkClient, CofhesdkError, CofhesdkErrorCode } from '@/core';
|
|
2
2
|
import { arbSepolia as cofhesdkArbSepolia } from '@/chains';
|
|
3
3
|
|
|
4
4
|
import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
|
|
@@ -60,11 +60,16 @@ describe('@cofhe/node - Client Integration Tests', () => {
|
|
|
60
60
|
});
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
describe('Environment', () => {
|
|
64
|
+
it('should have the correct environment', () => {
|
|
65
|
+
expect(cofhesdkClient.config.environment).toBe('node');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
63
69
|
describe('Real Connection', () => {
|
|
64
70
|
it('should connect to real chain', async () => {
|
|
65
|
-
|
|
71
|
+
await cofhesdkClient.connect(publicClient, walletClient);
|
|
66
72
|
|
|
67
|
-
expect(result.success).toBe(true);
|
|
68
73
|
expect(cofhesdkClient.connected).toBe(true);
|
|
69
74
|
|
|
70
75
|
const snapshot = cofhesdkClient.getSnapshot();
|
|
@@ -74,15 +79,17 @@ describe('@cofhe/node - Client Integration Tests', () => {
|
|
|
74
79
|
}, 30000);
|
|
75
80
|
|
|
76
81
|
it('should handle real network errors', async () => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
try {
|
|
83
|
+
await cofhesdkClient.connect(
|
|
84
|
+
{
|
|
85
|
+
getChainId: vi.fn().mockRejectedValue(new Error('Network error')),
|
|
86
|
+
} as unknown as PublicClient,
|
|
87
|
+
walletClient
|
|
88
|
+
);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
expect(error).toBeInstanceOf(CofhesdkError);
|
|
91
|
+
expect((error as CofhesdkError).code).toBe(CofhesdkErrorCode.PublicWalletGetChainIdFailed);
|
|
92
|
+
}
|
|
86
93
|
}, 30000);
|
|
87
94
|
});
|
|
88
95
|
|
|
@@ -113,23 +120,11 @@ describe('@cofhe/node - Client Integration Tests', () => {
|
|
|
113
120
|
}, 30000);
|
|
114
121
|
});
|
|
115
122
|
|
|
116
|
-
describe('Initialization Results', () => {
|
|
117
|
-
it('should have keyFetchResult promise', () => {
|
|
118
|
-
expect(cofhesdkClient.initializationResults).toBeDefined();
|
|
119
|
-
expect(cofhesdkClient.initializationResults.keyFetchResult).toBeInstanceOf(Promise);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('should resolve keyFetchResult', async () => {
|
|
123
|
-
const result = await cofhesdkClient.initializationResults.keyFetchResult;
|
|
124
|
-
expect(result.success).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
123
|
describe('Builder Creation', () => {
|
|
129
124
|
it('should create encrypt builder after connection', async () => {
|
|
130
125
|
await cofhesdkClient.connect(publicClient, walletClient);
|
|
131
126
|
|
|
132
|
-
const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2 }]);
|
|
127
|
+
const builder = cofhesdkClient.encryptInputs([{ data: 100n, utype: 2, securityZone: 0 }]);
|
|
133
128
|
|
|
134
129
|
expect(builder).toBeDefined();
|
|
135
130
|
expect(typeof builder.setChainId).toBe('function');
|