@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 +6 -0
- package/dist/web.cjs +18 -7
- package/dist/web.js +18 -6
- package/dist/zkProve.worker.cjs +69 -64
- package/dist/zkProve.worker.js +69 -64
- package/package.json +2 -2
- package/web/index.ts +22 -7
- package/web/zkProve.worker.ts +93 -84
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
|
|
4558
|
-
await
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
196
|
-
await
|
|
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(
|
|
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
|
};
|
package/dist/zkProve.worker.cjs
CHANGED
|
@@ -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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
+
}
|
package/dist/zkProve.worker.js
CHANGED
|
@@ -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
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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.
|
|
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
|
-
//
|
|
23
|
-
|
|
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
|
|
35
|
-
await
|
|
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(
|
|
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 };
|
package/web/zkProve.worker.ts
CHANGED
|
@@ -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
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
69
|
+
if (!tfheModule) {
|
|
70
|
+
throw new Error('TFHE module not initialized');
|
|
71
|
+
}
|
|
110
72
|
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
} as ZkProveWorkerResponse);
|
|
138
|
+
// Signal ready - send proper message format
|
|
139
|
+
self.postMessage({
|
|
140
|
+
id: 'init',
|
|
141
|
+
type: 'ready',
|
|
142
|
+
} as ZkProveWorkerResponse);
|
|
143
|
+
}
|