@cofhe/sdk 0.4.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 +38 -0
- package/adapters/{ethers5.test.ts → test/ethers5.test.ts} +2 -2
- package/adapters/{ethers6.test.ts → test/ethers6.test.ts} +2 -2
- package/adapters/{hardhat.hh2.test.ts → test/hardhat.hh2.test.ts} +2 -2
- package/adapters/{index.test.ts → test/index.test.ts} +1 -1
- package/adapters/{wagmi.test.ts → test/wagmi.test.ts} +1 -1
- package/chains/{chains.test.ts → test/chains.test.ts} +1 -1
- package/core/client.ts +11 -1
- package/core/clientTypes.ts +3 -1
- package/core/consts.ts +9 -0
- package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
- package/core/decrypt/decryptForTxBuilder.ts +16 -2
- package/core/decrypt/decryptForViewBuilder.ts +14 -7
- package/core/decrypt/polling.ts +14 -0
- package/core/decrypt/tnDecryptV2.ts +250 -110
- package/core/decrypt/tnSealOutputV2.ts +245 -104
- package/core/decrypt/verifyDecryptResult.ts +65 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +6 -6
- package/core/encrypt/zkPackProveVerify.ts +10 -19
- package/core/fetchKeys.ts +0 -2
- package/core/index.ts +9 -1
- package/core/keyStore.ts +5 -2
- package/core/permits.ts +5 -0
- package/core/{client.test.ts → test/client.test.ts} +7 -7
- package/core/{config.test.ts → test/config.test.ts} +1 -1
- package/core/test/decrypt.test.ts +252 -0
- package/core/test/decryptBuilders.test.ts +390 -0
- package/core/{encrypt → test}/encryptInputsBuilder.test.ts +61 -6
- package/core/{fetchKeys.test.ts → test/fetchKeys.test.ts} +3 -3
- package/core/{keyStore.test.ts → test/keyStore.test.ts} +5 -3
- package/core/{permits.test.ts → test/permits.test.ts} +42 -1
- package/core/test/pollCallbacks.test.ts +563 -0
- package/core/types.ts +13 -0
- package/dist/chains.d.cts +2 -2
- package/dist/chains.d.ts +2 -2
- package/dist/chunk-4FP4V35O.js +13 -0
- package/dist/{chunk-NWDKXBIP.js → chunk-MRCKUMOS.js} +62 -22
- package/dist/{chunk-MXND5SVN.js → chunk-S7OKGLFD.js} +485 -207
- package/dist/{clientTypes-kkrRdawm.d.ts → clientTypes-BSbwairE.d.cts} +23 -6
- package/dist/{clientTypes-ACVWbrXL.d.cts → clientTypes-DDmcgZ0a.d.ts} +23 -6
- package/dist/core.cjs +561 -244
- package/dist/core.d.cts +24 -6
- package/dist/core.d.ts +24 -6
- package/dist/core.js +3 -2
- package/dist/node.cjs +566 -246
- package/dist/node.d.cts +3 -3
- package/dist/node.d.ts +3 -3
- package/dist/node.js +14 -7
- package/dist/{permit-MZ502UBl.d.cts → permit-DnVMDT5h.d.cts} +34 -4
- package/dist/{permit-MZ502UBl.d.ts → permit-DnVMDT5h.d.ts} +34 -4
- package/dist/permits.cjs +66 -29
- package/dist/permits.d.cts +18 -13
- package/dist/permits.d.ts +18 -13
- package/dist/permits.js +2 -1
- package/dist/web.cjs +604 -256
- package/dist/web.d.cts +8 -4
- package/dist/web.d.ts +8 -4
- package/dist/web.js +49 -14
- package/dist/zkProve.worker.cjs +72 -64
- package/dist/zkProve.worker.js +71 -64
- package/node/index.ts +13 -4
- package/node/test/client.test.ts +25 -0
- package/node/test/config.test.ts +16 -0
- package/node/test/inherited.test.ts +244 -0
- package/node/test/tfheinit.test.ts +56 -0
- package/package.json +24 -22
- package/permits/permit.ts +31 -5
- package/permits/sealing.ts +1 -1
- package/permits/{localstorage.test.ts → test/localstorage.test.ts} +2 -2
- package/permits/{permit.test.ts → test/permit.test.ts} +35 -1
- package/permits/{sealing.test.ts → test/sealing.test.ts} +1 -1
- package/permits/{store.test.ts → test/store.test.ts} +2 -2
- package/permits/{validation.test.ts → test/validation.test.ts} +82 -6
- package/permits/types.ts +1 -1
- package/permits/validation.ts +42 -2
- package/web/const.ts +2 -0
- package/web/index.ts +40 -11
- package/web/storage.ts +18 -3
- package/web/{client.web.test.ts → test/client.web.test.ts} +13 -1
- package/web/test/config.web.test.ts +16 -0
- package/web/test/inherited.web.test.ts +245 -0
- package/web/test/tfheinit.web.test.ts +62 -0
- package/web/{worker.config.web.test.ts → test/worker.config.web.test.ts} +1 -1
- package/web/{worker.output.web.test.ts → test/worker.output.web.test.ts} +1 -1
- package/web/{workerManager.test.ts → test/workerManager.test.ts} +1 -1
- package/web/{workerManager.web.test.ts → test/workerManager.web.test.ts} +1 -1
- package/web/zkProve.worker.ts +94 -84
- package/node/client.test.ts +0 -147
- package/node/config.test.ts +0 -68
- package/node/encryptInputs.test.ts +0 -155
- package/web/config.web.test.ts +0 -69
- package/web/encryptInputs.web.test.ts +0 -172
- package/web/worker.builder.web.test.ts +0 -148
- /package/dist/{types-YiAC4gig.d.cts → types-C07FK-cL.d.cts} +0 -0
- /package/dist/{types-YiAC4gig.d.ts → types-C07FK-cL.d.ts} +0 -0
package/web/zkProve.worker.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
/// <reference lib="webworker" />
|
|
7
7
|
/* eslint-disable no-undef */
|
|
8
8
|
|
|
9
|
+
import { TFHE_RS_SAFE_SERIALIZATION_SIZE_LIMIT } from '../core/consts';
|
|
9
10
|
import type { ZkProveWorkerRequest, ZkProveWorkerResponse } from '../core/encrypt/zkPackProveVerify.js';
|
|
10
11
|
|
|
11
12
|
// TFHE module (will be initialized on first use)
|
|
@@ -41,93 +42,102 @@ function fromHexString(hexString: string): Uint8Array {
|
|
|
41
42
|
return new Uint8Array(arr.map((byte) => parseInt(byte, 16)));
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (!tfheModule) {
|
|
64
|
-
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;
|
|
65
63
|
}
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const fheKey = tfheModule.TfheCompactPublicKey.deserialize(fheKeyBytes);
|
|
72
|
-
const crs = tfheModule.CompactPkeCrs.deserialize(crsBytes);
|
|
73
|
-
|
|
74
|
-
// Create builder
|
|
75
|
-
const builder = tfheModule.ProvenCompactCiphertextList.builder(fheKey);
|
|
76
|
-
|
|
77
|
-
// Pack all items (duplicate of zkPack logic)
|
|
78
|
-
for (const item of items) {
|
|
79
|
-
switch (item.utype) {
|
|
80
|
-
case 'bool':
|
|
81
|
-
builder.push_boolean(Boolean(item.data));
|
|
82
|
-
break;
|
|
83
|
-
case 'uint8':
|
|
84
|
-
builder.push_u8(Number(item.data));
|
|
85
|
-
break;
|
|
86
|
-
case 'uint16':
|
|
87
|
-
builder.push_u16(Number(item.data));
|
|
88
|
-
break;
|
|
89
|
-
case 'uint32':
|
|
90
|
-
builder.push_u32(Number(item.data));
|
|
91
|
-
break;
|
|
92
|
-
case 'uint64':
|
|
93
|
-
builder.push_u64(BigInt(item.data));
|
|
94
|
-
break;
|
|
95
|
-
case 'uint128':
|
|
96
|
-
builder.push_u128(BigInt(item.data));
|
|
97
|
-
break;
|
|
98
|
-
case 'uint160':
|
|
99
|
-
builder.push_u160(BigInt(item.data));
|
|
100
|
-
break;
|
|
101
|
-
default:
|
|
102
|
-
throw new Error(`Unsupported type: ${item.utype}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
65
|
+
try {
|
|
66
|
+
// Initialize TFHE if needed
|
|
67
|
+
await initTfhe();
|
|
105
68
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
69
|
+
if (!tfheModule) {
|
|
70
|
+
throw new Error('TFHE module not initialized');
|
|
71
|
+
}
|
|
109
72
|
|
|
110
|
-
|
|
111
|
-
|
|
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
|
+
}
|
|
112
114
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
+
};
|
|
128
137
|
|
|
129
|
-
// Signal ready - send proper message format
|
|
130
|
-
self.postMessage({
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
} as ZkProveWorkerResponse);
|
|
138
|
+
// Signal ready - send proper message format
|
|
139
|
+
self.postMessage({
|
|
140
|
+
id: 'init',
|
|
141
|
+
type: 'ready',
|
|
142
|
+
} as ZkProveWorkerResponse);
|
|
143
|
+
}
|
package/node/client.test.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { type CofheClient, CofheError, CofheErrorCode } from '@/core';
|
|
2
|
-
import { arbSepolia as cofheArbSepolia } from '@/chains';
|
|
3
|
-
|
|
4
|
-
import { describe, it, expect, beforeAll, beforeEach, vi } from 'vitest';
|
|
5
|
-
import type { PublicClient, WalletClient } from 'viem';
|
|
6
|
-
import { createPublicClient, createWalletClient, http } from 'viem';
|
|
7
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
8
|
-
import { arbitrumSepolia as viemArbitrumSepolia } from 'viem/chains';
|
|
9
|
-
import { createCofheClient, createCofheConfig } from './index.js';
|
|
10
|
-
|
|
11
|
-
// Real test setup - no mocks
|
|
12
|
-
const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
|
|
13
|
-
const TEST_ACCOUNT = privateKeyToAccount(TEST_PRIVATE_KEY).address;
|
|
14
|
-
|
|
15
|
-
describe('@cofhe/node - Client Integration Tests', () => {
|
|
16
|
-
let cofheClient: CofheClient;
|
|
17
|
-
let publicClient: PublicClient;
|
|
18
|
-
let walletClient: WalletClient;
|
|
19
|
-
|
|
20
|
-
beforeAll(() => {
|
|
21
|
-
// Create real viem clients
|
|
22
|
-
publicClient = createPublicClient({
|
|
23
|
-
chain: viemArbitrumSepolia,
|
|
24
|
-
transport: http(),
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const account = privateKeyToAccount(TEST_PRIVATE_KEY);
|
|
28
|
-
walletClient = createWalletClient({
|
|
29
|
-
chain: viemArbitrumSepolia,
|
|
30
|
-
transport: http(),
|
|
31
|
-
account,
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
const config = createCofheConfig({
|
|
37
|
-
supportedChains: [cofheArbSepolia],
|
|
38
|
-
});
|
|
39
|
-
cofheClient = createCofheClient(config);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('Real Client Initialization', () => {
|
|
43
|
-
it('should create a client with real node-tfhe', () => {
|
|
44
|
-
expect(cofheClient).toBeDefined();
|
|
45
|
-
expect(cofheClient.config).toBeDefined();
|
|
46
|
-
expect(cofheClient.connected).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should automatically use filesystem storage as default', () => {
|
|
50
|
-
expect(cofheClient.config.fheKeyStorage).toBeDefined();
|
|
51
|
-
expect(cofheClient.config.fheKeyStorage).not.toBeNull();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should have all expected methods', () => {
|
|
55
|
-
expect(typeof cofheClient.connect).toBe('function');
|
|
56
|
-
expect(typeof cofheClient.encryptInputs).toBe('function');
|
|
57
|
-
expect(typeof cofheClient.decryptForView).toBe('function');
|
|
58
|
-
expect(typeof cofheClient.getSnapshot).toBe('function');
|
|
59
|
-
expect(typeof cofheClient.subscribe).toBe('function');
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('Environment', () => {
|
|
64
|
-
it('should have the correct environment', () => {
|
|
65
|
-
expect(cofheClient.config.environment).toBe('node');
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('Real Connection', () => {
|
|
70
|
-
it('should connect to real chain', async () => {
|
|
71
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
72
|
-
|
|
73
|
-
expect(cofheClient.connected).toBe(true);
|
|
74
|
-
|
|
75
|
-
const snapshot = cofheClient.getSnapshot();
|
|
76
|
-
expect(snapshot.connected).toBe(true);
|
|
77
|
-
expect(snapshot.chainId).toBe(cofheArbSepolia.id);
|
|
78
|
-
expect(snapshot.account).toBe(TEST_ACCOUNT);
|
|
79
|
-
}, 30000);
|
|
80
|
-
|
|
81
|
-
it('should handle real network errors', async () => {
|
|
82
|
-
try {
|
|
83
|
-
await cofheClient.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(CofheError);
|
|
91
|
-
expect((error as CofheError).code).toBe(CofheErrorCode.PublicWalletGetChainIdFailed);
|
|
92
|
-
}
|
|
93
|
-
}, 30000);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
describe('State Management', () => {
|
|
97
|
-
it('should track connection state changes', async () => {
|
|
98
|
-
const states: any[] = [];
|
|
99
|
-
const unsubscribe = cofheClient.subscribe((snapshot) => {
|
|
100
|
-
states.push({ ...snapshot });
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
104
|
-
|
|
105
|
-
unsubscribe();
|
|
106
|
-
|
|
107
|
-
expect(states.length).toBeGreaterThan(0);
|
|
108
|
-
|
|
109
|
-
// First state should be connecting
|
|
110
|
-
const firstState = states.find((s) => s.connecting);
|
|
111
|
-
expect(firstState).toBeDefined();
|
|
112
|
-
expect(firstState?.connecting).toBe(true);
|
|
113
|
-
expect(firstState?.connected).toBe(false);
|
|
114
|
-
|
|
115
|
-
// Last state should be connected
|
|
116
|
-
const lastState = states[states.length - 1];
|
|
117
|
-
expect(lastState.connected).toBe(true);
|
|
118
|
-
expect(lastState.connecting).toBe(false);
|
|
119
|
-
expect(lastState.chainId).toBe(cofheArbSepolia.id);
|
|
120
|
-
}, 30000);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
describe('Builder Creation', () => {
|
|
124
|
-
it('should create encrypt builder after connection', async () => {
|
|
125
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
126
|
-
|
|
127
|
-
const builder = cofheClient.encryptInputs([{ data: 100n, utype: 2, securityZone: 0 }]);
|
|
128
|
-
|
|
129
|
-
expect(builder).toBeDefined();
|
|
130
|
-
expect(typeof builder.setChainId).toBe('function');
|
|
131
|
-
expect(typeof builder.setAccount).toBe('function');
|
|
132
|
-
expect(typeof builder.setSecurityZone).toBe('function');
|
|
133
|
-
expect(typeof builder.execute).toBe('function');
|
|
134
|
-
}, 30000);
|
|
135
|
-
|
|
136
|
-
it('should create decrypt builder after connection', async () => {
|
|
137
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
138
|
-
|
|
139
|
-
const builder = cofheClient.decryptForView('0x123', 2);
|
|
140
|
-
|
|
141
|
-
expect(builder).toBeDefined();
|
|
142
|
-
expect(typeof builder.setChainId).toBe('function');
|
|
143
|
-
expect(typeof builder.setAccount).toBe('function');
|
|
144
|
-
expect(typeof builder.execute).toBe('function');
|
|
145
|
-
}, 30000);
|
|
146
|
-
});
|
|
147
|
-
});
|
package/node/config.test.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { arbSepolia } from '@/chains';
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
4
|
-
import { createCofheConfig, createCofheClient } from './index.js';
|
|
5
|
-
|
|
6
|
-
describe('@cofhe/node - Config', () => {
|
|
7
|
-
describe('createCofheConfig', () => {
|
|
8
|
-
it('should automatically inject filesystem storage as default', () => {
|
|
9
|
-
const config = createCofheConfig({
|
|
10
|
-
supportedChains: [arbSepolia],
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
expect(config.fheKeyStorage).toBeDefined();
|
|
14
|
-
expect(config.fheKeyStorage).not.toBeNull();
|
|
15
|
-
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should allow overriding storage', async () => {
|
|
19
|
-
const customStorage = {
|
|
20
|
-
getItem: () => Promise.resolve(10),
|
|
21
|
-
setItem: () => Promise.resolve(),
|
|
22
|
-
removeItem: () => Promise.resolve(),
|
|
23
|
-
};
|
|
24
|
-
const config = createCofheConfig({
|
|
25
|
-
supportedChains: [arbSepolia],
|
|
26
|
-
fheKeyStorage: customStorage,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
expect(await config.fheKeyStorage!.getItem('test')).toBe(10);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should allow null storage', () => {
|
|
33
|
-
const config = createCofheConfig({
|
|
34
|
-
supportedChains: [arbSepolia],
|
|
35
|
-
fheKeyStorage: null,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
expect(config.fheKeyStorage).toBeNull();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should preserve all other config options', () => {
|
|
42
|
-
const config = createCofheConfig({
|
|
43
|
-
supportedChains: [arbSepolia],
|
|
44
|
-
mocks: {
|
|
45
|
-
decryptDelay: 0,
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
50
|
-
expect(config.mocks.decryptDelay).toBe(0);
|
|
51
|
-
expect(config.fheKeyStorage).toBeDefined();
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe('createCofheClient with config', () => {
|
|
56
|
-
it('should create client with validated config', () => {
|
|
57
|
-
const config = createCofheConfig({
|
|
58
|
-
supportedChains: [arbSepolia],
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const client = createCofheClient(config);
|
|
62
|
-
|
|
63
|
-
expect(client).toBeDefined();
|
|
64
|
-
expect(client.config).toBe(config);
|
|
65
|
-
expect(client.config.fheKeyStorage).toBeDefined();
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
});
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import { Encryptable, FheTypes, type CofheClient, CofheErrorCode, CofheError } from '@/core';
|
|
2
|
-
import { arbSepolia as cofheArbSepolia } from '@/chains';
|
|
3
|
-
|
|
4
|
-
import { describe, it, expect, beforeAll, beforeEach } from 'vitest';
|
|
5
|
-
import type { PublicClient, WalletClient } from 'viem';
|
|
6
|
-
import { createPublicClient, createWalletClient, http } from 'viem';
|
|
7
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
8
|
-
import { arbitrumSepolia as viemArbitrumSepolia } from 'viem/chains';
|
|
9
|
-
import { createCofheClient, createCofheConfig } from './index.js';
|
|
10
|
-
|
|
11
|
-
// Real test setup - using actual node-tfhe
|
|
12
|
-
const TEST_PRIVATE_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
|
|
13
|
-
|
|
14
|
-
describe('@cofhe/node - Encrypt Inputs', () => {
|
|
15
|
-
let cofheClient: CofheClient;
|
|
16
|
-
let publicClient: PublicClient;
|
|
17
|
-
let walletClient: WalletClient;
|
|
18
|
-
|
|
19
|
-
beforeAll(() => {
|
|
20
|
-
// Create real viem clients
|
|
21
|
-
publicClient = createPublicClient({
|
|
22
|
-
chain: viemArbitrumSepolia,
|
|
23
|
-
transport: http(),
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const account = privateKeyToAccount(TEST_PRIVATE_KEY);
|
|
27
|
-
walletClient = createWalletClient({
|
|
28
|
-
chain: viemArbitrumSepolia,
|
|
29
|
-
transport: http(),
|
|
30
|
-
account,
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
beforeEach(() => {
|
|
35
|
-
const config = createCofheConfig({
|
|
36
|
-
supportedChains: [cofheArbSepolia],
|
|
37
|
-
});
|
|
38
|
-
cofheClient = createCofheClient(config);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('Real TFHE Initialization', () => {
|
|
42
|
-
it('should initialize node-tfhe on first encryption', async () => {
|
|
43
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
44
|
-
|
|
45
|
-
// This will trigger real TFHE initialization
|
|
46
|
-
const encrypted = await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
47
|
-
|
|
48
|
-
// If we get here, TFHE was initialized successfully
|
|
49
|
-
expect(encrypted).toBeDefined();
|
|
50
|
-
}, 60000); // Longer timeout for real operations
|
|
51
|
-
|
|
52
|
-
it('should handle multiple encryptions without re-initializing', async () => {
|
|
53
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
54
|
-
|
|
55
|
-
// First encryption
|
|
56
|
-
await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
57
|
-
|
|
58
|
-
// Second encryption should reuse initialization
|
|
59
|
-
await cofheClient.encryptInputs([Encryptable.uint64(50n)]).execute();
|
|
60
|
-
}, 120000);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('Real Encryption', () => {
|
|
64
|
-
it('should encrypt a bool with real TFHE', async () => {
|
|
65
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
66
|
-
|
|
67
|
-
const encrypted = await cofheClient.encryptInputs([Encryptable.bool(true)]).execute();
|
|
68
|
-
|
|
69
|
-
expect(encrypted.length).toBe(1);
|
|
70
|
-
expect(encrypted[0].utype).toBe(FheTypes.Bool);
|
|
71
|
-
expect(encrypted[0].ctHash).toBeDefined();
|
|
72
|
-
expect(typeof encrypted[0].ctHash).toBe('bigint');
|
|
73
|
-
expect(encrypted[0].signature).toBeDefined();
|
|
74
|
-
expect(typeof encrypted[0].signature).toBe('string');
|
|
75
|
-
expect(encrypted[0].securityZone).toBe(0);
|
|
76
|
-
}, 60000);
|
|
77
|
-
|
|
78
|
-
it('should encrypt all supported types together', async () => {
|
|
79
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
80
|
-
|
|
81
|
-
const inputs = [
|
|
82
|
-
Encryptable.bool(false),
|
|
83
|
-
Encryptable.uint8(1n),
|
|
84
|
-
Encryptable.uint16(2n),
|
|
85
|
-
Encryptable.uint32(3n),
|
|
86
|
-
Encryptable.uint64(4n),
|
|
87
|
-
Encryptable.uint128(5n),
|
|
88
|
-
Encryptable.address('0x742d35Cc6634C0532925a3b844D16faC4c175E99'),
|
|
89
|
-
];
|
|
90
|
-
|
|
91
|
-
const encrypted = await cofheClient.encryptInputs(inputs).execute();
|
|
92
|
-
|
|
93
|
-
expect(encrypted.length).toBe(7);
|
|
94
|
-
// Verify each type
|
|
95
|
-
expect(encrypted[0].utype).toBe(FheTypes.Bool);
|
|
96
|
-
expect(encrypted[1].utype).toBe(FheTypes.Uint8);
|
|
97
|
-
expect(encrypted[2].utype).toBe(FheTypes.Uint16);
|
|
98
|
-
expect(encrypted[3].utype).toBe(FheTypes.Uint32);
|
|
99
|
-
expect(encrypted[4].utype).toBe(FheTypes.Uint64);
|
|
100
|
-
expect(encrypted[5].utype).toBe(FheTypes.Uint128);
|
|
101
|
-
expect(encrypted[6].utype).toBe(FheTypes.Uint160);
|
|
102
|
-
}, 90000); // Longer timeout for multiple encryptions
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Real Builder Pattern', () => {
|
|
106
|
-
it('should support chaining builder methods with real encryption', async () => {
|
|
107
|
-
await cofheClient.connect(publicClient, walletClient);
|
|
108
|
-
|
|
109
|
-
const snapshot = cofheClient.getSnapshot();
|
|
110
|
-
const encrypted = await cofheClient
|
|
111
|
-
.encryptInputs([Encryptable.uint128(100n)])
|
|
112
|
-
.setChainId(snapshot.chainId!)
|
|
113
|
-
.setAccount(snapshot.account!)
|
|
114
|
-
.setSecurityZone(0)
|
|
115
|
-
.execute();
|
|
116
|
-
|
|
117
|
-
expect(encrypted.length).toBe(1);
|
|
118
|
-
expect(encrypted[0].utype).toBe(FheTypes.Uint128);
|
|
119
|
-
}, 60000);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe('Real Error Handling', () => {
|
|
123
|
-
it('should fail gracefully when not connected', async () => {
|
|
124
|
-
// Don't connect the client
|
|
125
|
-
try {
|
|
126
|
-
await cofheClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
127
|
-
} catch (error) {
|
|
128
|
-
expect(error).toBeInstanceOf(CofheError);
|
|
129
|
-
expect((error as CofheError).code).toBe(CofheErrorCode.NotConnected);
|
|
130
|
-
}
|
|
131
|
-
}, 30000);
|
|
132
|
-
|
|
133
|
-
it('should handle invalid CoFHE URL', async () => {
|
|
134
|
-
const badConfig = createCofheConfig({
|
|
135
|
-
supportedChains: [
|
|
136
|
-
{
|
|
137
|
-
...cofheArbSepolia,
|
|
138
|
-
coFheUrl: 'http://invalid-cofhe-url.local',
|
|
139
|
-
verifierUrl: 'http://invalid-verifier-url.local',
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const badClient = createCofheClient(badConfig);
|
|
145
|
-
await badClient.connect(publicClient, walletClient);
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
await badClient.encryptInputs([Encryptable.uint128(100n)]).execute();
|
|
149
|
-
} catch (error) {
|
|
150
|
-
expect(error).toBeInstanceOf(CofheError);
|
|
151
|
-
expect((error as CofheError).code).toBe(CofheErrorCode.ZkVerifyFailed);
|
|
152
|
-
}
|
|
153
|
-
}, 60000);
|
|
154
|
-
});
|
|
155
|
-
});
|
package/web/config.web.test.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { arbSepolia } from '@/chains';
|
|
2
|
-
|
|
3
|
-
import { describe, it, expect } from 'vitest';
|
|
4
|
-
import { createCofheConfig, createCofheClient } from './index.js';
|
|
5
|
-
|
|
6
|
-
describe('@cofhe/web - Config', () => {
|
|
7
|
-
describe('createCofheConfig', () => {
|
|
8
|
-
it('should automatically inject IndexedDB storage as default', () => {
|
|
9
|
-
const config = createCofheConfig({
|
|
10
|
-
supportedChains: [arbSepolia],
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
expect(config.fheKeyStorage).toBeDefined();
|
|
14
|
-
expect(config.fheKeyStorage).not.toBeNull();
|
|
15
|
-
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should allow overriding storage', async () => {
|
|
19
|
-
const customStorage = {
|
|
20
|
-
getItem: () => Promise.resolve(10),
|
|
21
|
-
setItem: () => Promise.resolve(),
|
|
22
|
-
removeItem: () => Promise.resolve(),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const config = createCofheConfig({
|
|
26
|
-
supportedChains: [arbSepolia],
|
|
27
|
-
fheKeyStorage: customStorage,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
expect(await config.fheKeyStorage!.getItem('test')).toBe(10);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should allow null storage', () => {
|
|
34
|
-
const config = createCofheConfig({
|
|
35
|
-
supportedChains: [arbSepolia],
|
|
36
|
-
fheKeyStorage: null,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
expect(config.fheKeyStorage).toBeNull();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('should preserve all other config options', () => {
|
|
43
|
-
const config = createCofheConfig({
|
|
44
|
-
supportedChains: [arbSepolia],
|
|
45
|
-
mocks: {
|
|
46
|
-
decryptDelay: 500,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
expect(config.supportedChains).toEqual([arbSepolia]);
|
|
51
|
-
expect(config.mocks.decryptDelay).toBe(500);
|
|
52
|
-
expect(config.fheKeyStorage).toBeDefined();
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('createCofheClient with config', () => {
|
|
57
|
-
it('should create client with validated config', () => {
|
|
58
|
-
const config = createCofheConfig({
|
|
59
|
-
supportedChains: [arbSepolia],
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const client = createCofheClient(config);
|
|
63
|
-
|
|
64
|
-
expect(client).toBeDefined();
|
|
65
|
-
expect(client.config).toBe(config);
|
|
66
|
-
expect(client.config.fheKeyStorage).toBeDefined();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
});
|