@cofhe/sdk 0.5.0 → 0.5.2
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 +16 -0
- package/adapters/test/ethers5.test.ts +1 -1
- package/adapters/test/ethers6.test.ts +1 -1
- package/adapters/test/wagmi.test.ts +1 -1
- package/core/decrypt/decryptForTxBuilder.ts +21 -0
- package/core/decrypt/decryptForViewBuilder.ts +19 -0
- package/core/decrypt/submitRetry.ts +126 -0
- package/core/decrypt/tnDecryptV2.ts +48 -53
- package/core/decrypt/tnSealOutputV2.ts +48 -54
- package/core/test/decryptBuilders.test.ts +28 -0
- package/core/test/pollCallbacks.test.ts +226 -0
- package/dist/{chunk-S7OKGLFD.js → chunk-YDOK4BDL.js} +253 -147
- package/dist/{clientTypes-BSbwairE.d.cts → clientTypes-BJbFeeno.d.cts} +5 -0
- package/dist/{clientTypes-DDmcgZ0a.d.ts → clientTypes-CEno_BEf.d.ts} +5 -0
- package/dist/core.cjs +253 -147
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +1 -1
- package/dist/node.cjs +208 -102
- package/dist/node.d.cts +1 -1
- package/dist/node.d.ts +1 -1
- package/dist/node.js +1 -1
- package/dist/web.cjs +226 -109
- package/dist/web.d.cts +1 -1
- package/dist/web.d.ts +1 -1
- package/dist/web.js +19 -7
- 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/test/tfheinit.web.test.ts +3 -3
- package/web/zkProve.worker.ts +93 -84
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.2",
|
|
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 };
|
|
@@ -53,10 +53,10 @@ describe('@cofhe/web - TFHE Initialization Browser Tests', () => {
|
|
|
53
53
|
await cofheClient.connect(publicClient, walletClient);
|
|
54
54
|
|
|
55
55
|
// First encryption
|
|
56
|
-
expect(cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute()).resolves.not.toThrow();
|
|
56
|
+
await expect(cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute()).resolves.not.toThrow();
|
|
57
57
|
|
|
58
58
|
// Second encryption should reuse initialization
|
|
59
|
-
expect(cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute()).resolves.not.toThrow();
|
|
60
|
-
},
|
|
59
|
+
await expect(cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute()).resolves.not.toThrow();
|
|
60
|
+
}, 120000);
|
|
61
61
|
});
|
|
62
62
|
});
|
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
|
+
}
|