@cofhe/sdk 0.5.0 → 0.5.1

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @cofhe/sdk Changelog
2
2
 
3
+ ## 0.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 342fd0f: Fix SSR compatibility (`@cofhe/sdk/web` no longer crashes Next.js builds with `self is not defined`) by lazy-loading `tfhe`. Align `@cofhe/mock-contracts` with `@fhenixprotocol/cofhe-contracts@^0.1.3` (updated `TestBed.sol` to use current decrypt API, added missing `ITaskManager` batch methods to `MockTaskManager.sol`).
8
+
3
9
  ## 0.5.0
4
10
 
5
11
  ### Minor Changes
package/dist/web.cjs CHANGED
@@ -9,13 +9,11 @@ var middleware = require('zustand/middleware');
9
9
  var immer = require('immer');
10
10
  var nacl = require('tweetnacl');
11
11
  var iframeSharedStorage = require('iframe-shared-storage');
12
- var init = require('tfhe');
13
12
 
14
13
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
15
 
17
16
  var nacl__default = /*#__PURE__*/_interopDefault(nacl);
18
- var init__default = /*#__PURE__*/_interopDefault(init);
19
17
 
20
18
  // core/client.ts
21
19
 
@@ -4550,15 +4548,25 @@ function terminateWorker() {
4550
4548
  function areWorkersAvailable() {
4551
4549
  return typeof Worker !== "undefined";
4552
4550
  }
4551
+
4552
+ // web/index.ts
4553
+ var tfheModule = null;
4553
4554
  var tfheInitialized = false;
4554
4555
  async function initTfhe() {
4555
4556
  if (tfheInitialized)
4556
4557
  return false;
4557
- await init__default.default();
4558
- await init.init_panic_hook();
4558
+ tfheModule = await import('tfhe');
4559
+ await tfheModule.default();
4560
+ await tfheModule.init_panic_hook();
4559
4561
  tfheInitialized = true;
4560
4562
  return true;
4561
4563
  }
4564
+ function requireTfhe() {
4565
+ if (!tfheModule) {
4566
+ throw new Error("TFHE not initialized \u2014 call initTfhe() (or any client method that triggers it) first");
4567
+ }
4568
+ return tfheModule;
4569
+ }
4562
4570
  var fromHexString2 = (hexString) => {
4563
4571
  const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
4564
4572
  const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
@@ -4567,10 +4575,13 @@ var fromHexString2 = (hexString) => {
4567
4575
  return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
4568
4576
  };
4569
4577
  var _deserializeTfhePublicKey = (buff) => {
4570
- return init.TfheCompactPublicKey.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
4578
+ return requireTfhe().TfheCompactPublicKey.safe_deserialize(
4579
+ fromHexString2(buff),
4580
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
4581
+ );
4571
4582
  };
4572
4583
  var _deserializeCompactPkeCrs = (buff) => {
4573
- return init.CompactPkeCrs.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
4584
+ return requireTfhe().CompactPkeCrs.safe_deserialize(fromHexString2(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
4574
4585
  };
4575
4586
  var tfhePublicKeyDeserializer = (buff) => {
4576
4587
  _deserializeTfhePublicKey(buff);
@@ -4580,7 +4591,7 @@ var compactPkeCrsDeserializer = (buff) => {
4580
4591
  };
4581
4592
  var zkBuilderAndCrsGenerator = (fhe, crs) => {
4582
4593
  const fhePublicKey = _deserializeTfhePublicKey(fhe);
4583
- const zkBuilder = init.ProvenCompactCiphertextList.builder(fhePublicKey);
4594
+ const zkBuilder = requireTfhe().ProvenCompactCiphertextList.builder(fhePublicKey);
4584
4595
  const zkCrs = _deserializeCompactPkeCrs(crs);
4585
4596
  return { zkBuilder, zkCrs };
4586
4597
  };
package/dist/web.js CHANGED
@@ -3,7 +3,6 @@ import './chunk-TBLR7NNE.js';
3
3
  import './chunk-MRCKUMOS.js';
4
4
  import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from './chunk-4FP4V35O.js';
5
5
  import { constructClient } from 'iframe-shared-storage';
6
- import init, { init_panic_hook, ProvenCompactCiphertextList, CompactPkeCrs, TfheCompactPublicKey } from 'tfhe';
7
6
 
8
7
  // web/const.ts
9
8
  var hasDOM = typeof globalThis?.document !== "undefined" && typeof globalThis?.window !== "undefined";
@@ -188,15 +187,25 @@ function terminateWorker() {
188
187
  function areWorkersAvailable() {
189
188
  return typeof Worker !== "undefined";
190
189
  }
190
+
191
+ // web/index.ts
192
+ var tfheModule = null;
191
193
  var tfheInitialized = false;
192
194
  async function initTfhe() {
193
195
  if (tfheInitialized)
194
196
  return false;
195
- await init();
196
- await init_panic_hook();
197
+ tfheModule = await import('tfhe');
198
+ await tfheModule.default();
199
+ await tfheModule.init_panic_hook();
197
200
  tfheInitialized = true;
198
201
  return true;
199
202
  }
203
+ function requireTfhe() {
204
+ if (!tfheModule) {
205
+ throw new Error("TFHE not initialized \u2014 call initTfhe() (or any client method that triggers it) first");
206
+ }
207
+ return tfheModule;
208
+ }
200
209
  var fromHexString = (hexString) => {
201
210
  const cleanString = hexString.length % 2 === 1 ? `0${hexString}` : hexString;
202
211
  const arr = cleanString.replace(/^0x/, "").match(/.{1,2}/g);
@@ -205,10 +214,13 @@ var fromHexString = (hexString) => {
205
214
  return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
206
215
  };
207
216
  var _deserializeTfhePublicKey = (buff) => {
208
- return TfheCompactPublicKey.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
217
+ return requireTfhe().TfheCompactPublicKey.safe_deserialize(
218
+ fromHexString(buff),
219
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
220
+ );
209
221
  };
210
222
  var _deserializeCompactPkeCrs = (buff) => {
211
- return CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
223
+ return requireTfhe().CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
212
224
  };
213
225
  var tfhePublicKeyDeserializer = (buff) => {
214
226
  _deserializeTfhePublicKey(buff);
@@ -218,7 +230,7 @@ var compactPkeCrsDeserializer = (buff) => {
218
230
  };
219
231
  var zkBuilderAndCrsGenerator = (fhe, crs) => {
220
232
  const fhePublicKey = _deserializeTfhePublicKey(fhe);
221
- const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
233
+ const zkBuilder = requireTfhe().ProvenCompactCiphertextList.builder(fhePublicKey);
222
234
  const zkCrs = _deserializeCompactPkeCrs(crs);
223
235
  return { zkBuilder, zkCrs };
224
236
  };
@@ -27,70 +27,75 @@ function fromHexString(hexString) {
27
27
  return new Uint8Array();
28
28
  return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
29
29
  }
30
- self.onmessage = async (event) => {
31
- const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
32
- if (type !== "zkProve") {
33
- self.postMessage({
34
- id,
35
- type: "error",
36
- error: "Invalid message type"
37
- });
38
- return;
39
- }
40
- try {
41
- await initTfhe();
42
- if (!tfheModule) {
43
- throw new Error("TFHE module not initialized");
30
+ if (typeof self !== "undefined") {
31
+ self.onmessage = async (event) => {
32
+ const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
33
+ if (type !== "zkProve") {
34
+ self.postMessage({
35
+ id,
36
+ type: "error",
37
+ error: "Invalid message type"
38
+ });
39
+ return;
44
40
  }
45
- const fheKeyBytes = fromHexString(fheKeyHex);
46
- const crsBytes = fromHexString(crsHex);
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);
49
- const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
50
- for (const item of items) {
51
- switch (item.utype) {
52
- case "bool":
53
- builder.push_boolean(Boolean(item.data));
54
- break;
55
- case "uint8":
56
- builder.push_u8(Number(item.data));
57
- break;
58
- case "uint16":
59
- builder.push_u16(Number(item.data));
60
- break;
61
- case "uint32":
62
- builder.push_u32(Number(item.data));
63
- break;
64
- case "uint64":
65
- builder.push_u64(BigInt(item.data));
66
- break;
67
- case "uint128":
68
- builder.push_u128(BigInt(item.data));
69
- break;
70
- case "uint160":
71
- builder.push_u160(BigInt(item.data));
72
- break;
73
- default:
74
- throw new Error(`Unsupported type: ${item.utype}`);
41
+ try {
42
+ await initTfhe();
43
+ if (!tfheModule) {
44
+ throw new Error("TFHE module not initialized");
45
+ }
46
+ const fheKeyBytes = fromHexString(fheKeyHex);
47
+ const crsBytes = fromHexString(crsHex);
48
+ const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(
49
+ fheKeyBytes,
50
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
51
+ );
52
+ const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
53
+ const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
54
+ for (const item of items) {
55
+ switch (item.utype) {
56
+ case "bool":
57
+ builder.push_boolean(Boolean(item.data));
58
+ break;
59
+ case "uint8":
60
+ builder.push_u8(Number(item.data));
61
+ break;
62
+ case "uint16":
63
+ builder.push_u16(Number(item.data));
64
+ break;
65
+ case "uint32":
66
+ builder.push_u32(Number(item.data));
67
+ break;
68
+ case "uint64":
69
+ builder.push_u64(BigInt(item.data));
70
+ break;
71
+ case "uint128":
72
+ builder.push_u128(BigInt(item.data));
73
+ break;
74
+ case "uint160":
75
+ builder.push_u160(BigInt(item.data));
76
+ break;
77
+ default:
78
+ throw new Error(`Unsupported type: ${item.utype}`);
79
+ }
75
80
  }
81
+ const metadataBytes = new Uint8Array(metadata);
82
+ const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
83
+ const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
84
+ self.postMessage({
85
+ id,
86
+ type: "success",
87
+ result: Array.from(result)
88
+ });
89
+ } catch (error) {
90
+ self.postMessage({
91
+ id,
92
+ type: "error",
93
+ error: error instanceof Error ? error.message : String(error)
94
+ });
76
95
  }
77
- const metadataBytes = new Uint8Array(metadata);
78
- const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
79
- const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
80
- self.postMessage({
81
- id,
82
- type: "success",
83
- result: Array.from(result)
84
- });
85
- } catch (error) {
86
- self.postMessage({
87
- id,
88
- type: "error",
89
- error: error instanceof Error ? error.message : String(error)
90
- });
91
- }
92
- };
93
- self.postMessage({
94
- id: "init",
95
- type: "ready"
96
- });
96
+ };
97
+ self.postMessage({
98
+ id: "init",
99
+ type: "ready"
100
+ });
101
+ }
@@ -24,70 +24,75 @@ function fromHexString(hexString) {
24
24
  return new Uint8Array();
25
25
  return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
26
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");
27
+ if (typeof self !== "undefined") {
28
+ self.onmessage = async (event) => {
29
+ const { id, type, fheKeyHex, crsHex, items, metadata } = event.data;
30
+ if (type !== "zkProve") {
31
+ self.postMessage({
32
+ id,
33
+ type: "error",
34
+ error: "Invalid message type"
35
+ });
36
+ return;
41
37
  }
42
- const fheKeyBytes = fromHexString(fheKeyHex);
43
- const crsBytes = fromHexString(crsHex);
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);
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}`);
38
+ try {
39
+ await initTfhe();
40
+ if (!tfheModule) {
41
+ throw new Error("TFHE module not initialized");
42
+ }
43
+ const fheKeyBytes = fromHexString(fheKeyHex);
44
+ const crsBytes = fromHexString(crsHex);
45
+ const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(
46
+ fheKeyBytes,
47
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
48
+ );
49
+ const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
50
+ const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
51
+ for (const item of items) {
52
+ switch (item.utype) {
53
+ case "bool":
54
+ builder.push_boolean(Boolean(item.data));
55
+ break;
56
+ case "uint8":
57
+ builder.push_u8(Number(item.data));
58
+ break;
59
+ case "uint16":
60
+ builder.push_u16(Number(item.data));
61
+ break;
62
+ case "uint32":
63
+ builder.push_u32(Number(item.data));
64
+ break;
65
+ case "uint64":
66
+ builder.push_u64(BigInt(item.data));
67
+ break;
68
+ case "uint128":
69
+ builder.push_u128(BigInt(item.data));
70
+ break;
71
+ case "uint160":
72
+ builder.push_u160(BigInt(item.data));
73
+ break;
74
+ default:
75
+ throw new Error(`Unsupported type: ${item.utype}`);
76
+ }
72
77
  }
78
+ const metadataBytes = new Uint8Array(metadata);
79
+ const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
80
+ const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
81
+ self.postMessage({
82
+ id,
83
+ type: "success",
84
+ result: Array.from(result)
85
+ });
86
+ } catch (error) {
87
+ self.postMessage({
88
+ id,
89
+ type: "error",
90
+ error: error instanceof Error ? error.message : String(error)
91
+ });
73
92
  }
74
- const metadataBytes = new Uint8Array(metadata);
75
- const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
76
- const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
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
- });
93
+ };
94
+ self.postMessage({
95
+ id: "init",
96
+ type: "ready"
97
+ });
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cofhe/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "description": "SDK for Fhenix COFHE coprocessor interaction",
6
6
  "main": "./dist/core.cjs",
@@ -101,8 +101,8 @@
101
101
  "tsup": "8.0.2",
102
102
  "typescript": "5.5.4",
103
103
  "vitest": "3.2.4",
104
- "@cofhe/test-setup": "0.0.0",
105
104
  "@cofhe/eslint-config": "0.2.1",
105
+ "@cofhe/test-setup": "0.0.0",
106
106
  "@cofhe/tsconfig": "0.1.2"
107
107
  },
108
108
  "publishConfig": {
package/web/index.ts CHANGED
@@ -19,8 +19,11 @@ import { createSsrStorage, createWebStorage } from './storage.js';
19
19
  // Import worker manager
20
20
  import { getWorkerManager, terminateWorker, areWorkersAvailable } from './workerManager.js';
21
21
 
22
- // Import tfhe for web
23
- import init, { init_panic_hook, TfheCompactPublicKey, ProvenCompactCiphertextList, CompactPkeCrs } from 'tfhe';
22
+ // Type-only import for tfhe — the runtime is loaded lazily via `await import('tfhe')`
23
+ // inside `initTfhe()` so that simply importing `@cofhe/sdk/web` (e.g. transitively
24
+ // through `@cofhe/react`) does not pull tfhe — and its worker helpers that
25
+ // reference `self` at module top — into the import graph during Next.js SSR.
26
+ import type { TfheCompactPublicKey, ProvenCompactCiphertextList, CompactPkeCrs } from 'tfhe';
24
27
  import { hasDOM } from './const';
25
28
 
26
29
  /**
@@ -28,15 +31,24 @@ import { hasDOM } from './const';
28
31
  * Called automatically on first encryption - users don't need to call this manually
29
32
  * @returns true if TFHE was initialized, false if already initialized
30
33
  */
34
+ let tfheModule: typeof import('tfhe') | null = null;
31
35
  let tfheInitialized = false;
32
36
  async function initTfhe(): Promise<boolean> {
33
37
  if (tfheInitialized) return false;
34
- await init();
35
- await init_panic_hook();
38
+ tfheModule = await import('tfhe');
39
+ await tfheModule.default();
40
+ await tfheModule.init_panic_hook();
36
41
  tfheInitialized = true;
37
42
  return true;
38
43
  }
39
44
 
45
+ function requireTfhe(): typeof import('tfhe') {
46
+ if (!tfheModule) {
47
+ throw new Error('TFHE not initialized — call initTfhe() (or any client method that triggers it) first');
48
+ }
49
+ return tfheModule;
50
+ }
51
+
40
52
  /**
41
53
  * Utility to convert the hex string key to a Uint8Array for use with tfhe
42
54
  */
@@ -48,11 +60,14 @@ const fromHexString = (hexString: string): Uint8Array => {
48
60
  };
49
61
 
50
62
  const _deserializeTfhePublicKey = (buff: string): TfheCompactPublicKey => {
51
- return TfheCompactPublicKey.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
63
+ return requireTfhe().TfheCompactPublicKey.safe_deserialize(
64
+ fromHexString(buff),
65
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
66
+ );
52
67
  };
53
68
 
54
69
  const _deserializeCompactPkeCrs = (buff: string): CompactPkeCrs => {
55
- return CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
70
+ return requireTfhe().CompactPkeCrs.safe_deserialize(fromHexString(buff), TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
56
71
  };
57
72
 
58
73
  /**
@@ -77,7 +92,7 @@ const compactPkeCrsDeserializer: FheKeyDeserializer = (buff: string): void => {
77
92
  */
78
93
  const zkBuilderAndCrsGenerator: ZkBuilderAndCrsGenerator = (fhe: string, crs: string) => {
79
94
  const fhePublicKey = _deserializeTfhePublicKey(fhe);
80
- const zkBuilder = ProvenCompactCiphertextList.builder(fhePublicKey);
95
+ const zkBuilder = requireTfhe().ProvenCompactCiphertextList.builder(fhePublicKey);
81
96
  const zkCrs = _deserializeCompactPkeCrs(crs);
82
97
 
83
98
  return { zkBuilder, zkCrs };
@@ -42,93 +42,102 @@ function fromHexString(hexString: string): Uint8Array {
42
42
  return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
43
43
  }
44
44
 
45
- /**
46
- * Main message handler
47
- */
48
- self.onmessage = async (event: MessageEvent) => {
49
- const { id, type, fheKeyHex, crsHex, items, metadata } = event.data as ZkProveWorkerRequest;
50
-
51
- if (type !== 'zkProve') {
52
- self.postMessage({
53
- id,
54
- type: 'error',
55
- error: 'Invalid message type',
56
- } as ZkProveWorkerResponse);
57
- return;
58
- }
59
-
60
- try {
61
- // Initialize TFHE if needed
62
- await initTfhe();
63
-
64
- if (!tfheModule) {
65
- throw new Error('TFHE module not initialized');
45
+ // Guard the top-level `self` references so this file is safe to evaluate in
46
+ // non-worker contexts (e.g. when bundlers like webpack pull the worker chunk
47
+ // into the server bundle for SSR). The body is dead code anywhere `self` is
48
+ // undefined, so skipping it is harmless.
49
+ if (typeof self !== 'undefined') {
50
+ /**
51
+ * Main message handler
52
+ */
53
+ self.onmessage = async (event: MessageEvent) => {
54
+ const { id, type, fheKeyHex, crsHex, items, metadata } = event.data as ZkProveWorkerRequest;
55
+
56
+ if (type !== 'zkProve') {
57
+ self.postMessage({
58
+ id,
59
+ type: 'error',
60
+ error: 'Invalid message type',
61
+ } as ZkProveWorkerResponse);
62
+ return;
66
63
  }
67
64
 
68
- // Deserialize FHE public key and CRS from hex strings
69
- const fheKeyBytes = fromHexString(fheKeyHex);
70
- const crsBytes = fromHexString(crsHex);
71
-
72
- const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(fheKeyBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
73
- const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
74
-
75
- // Create builder
76
- const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
77
-
78
- // Pack all items (duplicate of zkPack logic)
79
- for (const item of items) {
80
- switch (item.utype) {
81
- case 'bool':
82
- builder.push_boolean(Boolean(item.data));
83
- break;
84
- case 'uint8':
85
- builder.push_u8(Number(item.data));
86
- break;
87
- case 'uint16':
88
- builder.push_u16(Number(item.data));
89
- break;
90
- case 'uint32':
91
- builder.push_u32(Number(item.data));
92
- break;
93
- case 'uint64':
94
- builder.push_u64(BigInt(item.data));
95
- break;
96
- case 'uint128':
97
- builder.push_u128(BigInt(item.data));
98
- break;
99
- case 'uint160':
100
- builder.push_u160(BigInt(item.data));
101
- break;
102
- default:
103
- throw new Error(`Unsupported type: ${item.utype}`);
104
- }
105
- }
65
+ try {
66
+ // Initialize TFHE if needed
67
+ await initTfhe();
106
68
 
107
- // THE HEAVY OPERATION - but in worker thread!
108
- const metadataBytes = new Uint8Array(metadata);
109
- const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
69
+ if (!tfheModule) {
70
+ throw new Error('TFHE module not initialized');
71
+ }
110
72
 
111
- // Serialize result
112
- const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
73
+ // Deserialize FHE public key and CRS from hex strings
74
+ const fheKeyBytes = fromHexString(fheKeyHex);
75
+ const crsBytes = fromHexString(crsHex);
76
+
77
+ const fheKey = tfheModule.TfheCompactPublicKey.safe_deserialize(
78
+ fheKeyBytes,
79
+ TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT
80
+ );
81
+ const crs = tfheModule.CompactPkeCrs.safe_deserialize(crsBytes, TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
82
+
83
+ // Create builder
84
+ const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
85
+
86
+ // Pack all items (duplicate of zkPack logic)
87
+ for (const item of items) {
88
+ switch (item.utype) {
89
+ case 'bool':
90
+ builder.push_boolean(Boolean(item.data));
91
+ break;
92
+ case 'uint8':
93
+ builder.push_u8(Number(item.data));
94
+ break;
95
+ case 'uint16':
96
+ builder.push_u16(Number(item.data));
97
+ break;
98
+ case 'uint32':
99
+ builder.push_u32(Number(item.data));
100
+ break;
101
+ case 'uint64':
102
+ builder.push_u64(BigInt(item.data));
103
+ break;
104
+ case 'uint128':
105
+ builder.push_u128(BigInt(item.data));
106
+ break;
107
+ case 'uint160':
108
+ builder.push_u160(BigInt(item.data));
109
+ break;
110
+ default:
111
+ throw new Error(`Unsupported type: ${item.utype}`);
112
+ }
113
+ }
113
114
 
114
- // Send success response
115
- self.postMessage({
116
- id,
117
- type: 'success',
118
- result: Array.from(result),
119
- } as ZkProveWorkerResponse);
120
- } catch (error) {
121
- // Send error response
122
- self.postMessage({
123
- id,
124
- type: 'error',
125
- error: error instanceof Error ? error.message : String(error),
126
- } as ZkProveWorkerResponse);
127
- }
128
- };
115
+ // THE HEAVY OPERATION - but in worker thread!
116
+ const metadataBytes = new Uint8Array(metadata);
117
+ const compactList = builder.build_with_proof_packed(crs, metadataBytes, 1);
118
+
119
+ // Serialize result
120
+ const result = compactList.safe_serialize(TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT);
121
+
122
+ // Send success response
123
+ self.postMessage({
124
+ id,
125
+ type: 'success',
126
+ result: Array.from(result),
127
+ } as ZkProveWorkerResponse);
128
+ } catch (error) {
129
+ // Send error response
130
+ self.postMessage({
131
+ id,
132
+ type: 'error',
133
+ error: error instanceof Error ? error.message : String(error),
134
+ } as ZkProveWorkerResponse);
135
+ }
136
+ };
129
137
 
130
- // Signal ready - send proper message format
131
- self.postMessage({
132
- id: 'init',
133
- type: 'ready',
134
- } as ZkProveWorkerResponse);
138
+ // Signal ready - send proper message format
139
+ self.postMessage({
140
+ id: 'init',
141
+ type: 'ready',
142
+ } as ZkProveWorkerResponse);
143
+ }