@cofhe/sdk 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +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 +15 -5
- package/core/clientTypes.ts +7 -5
- package/core/consts.ts +9 -0
- package/core/decrypt/cofheMocksDecryptForTx.ts +14 -3
- package/core/decrypt/decryptForTxBuilder.ts +24 -10
- package/core/decrypt/decryptForViewBuilder.ts +14 -7
- package/core/decrypt/polling.ts +14 -0
- package/core/decrypt/tnDecryptUtils.ts +65 -0
- package/core/decrypt/{tnDecrypt.ts → tnDecryptV1.ts} +7 -70
- package/core/decrypt/tnDecryptV2.ts +483 -0
- 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 +8 -3
- 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 +21 -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-LWMRB6SD.js → chunk-S7OKGLFD.js} +615 -198
- package/dist/{clientTypes-Y43CKbOz.d.cts → clientTypes-BSbwairE.d.cts} +38 -13
- package/dist/{clientTypes-PQha8zes.d.ts → clientTypes-DDmcgZ0a.d.ts} +38 -13
- package/dist/core.cjs +691 -235
- package/dist/core.d.cts +24 -6
- package/dist/core.d.ts +24 -6
- package/dist/core.js +3 -2
- package/dist/node.cjs +696 -237
- 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.ts → permit-DnVMDT5h.d.cts} +34 -4
- package/dist/{permit-MZ502UBl.d.cts → 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 +718 -242
- package/dist/web.d.cts +8 -4
- package/dist/web.d.ts +8 -4
- package/dist/web.js +34 -11
- package/dist/zkProve.worker.cjs +6 -3
- package/dist/zkProve.worker.js +5 -3
- 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 +20 -6
- 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 +4 -3
- 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/core/permits.ts
CHANGED
|
@@ -75,6 +75,10 @@ const getHash = (permit: PermitHashFields) => {
|
|
|
75
75
|
return PermitUtils.getHash(permit);
|
|
76
76
|
};
|
|
77
77
|
|
|
78
|
+
const exportShared = (permit: Permit) => {
|
|
79
|
+
return PermitUtils.export(permit);
|
|
80
|
+
};
|
|
81
|
+
|
|
78
82
|
const serialize = (permit: Permit) => {
|
|
79
83
|
return PermitUtils.serialize(permit);
|
|
80
84
|
};
|
|
@@ -85,15 +89,15 @@ const deserialize = (serialized: SerializedPermit) => {
|
|
|
85
89
|
|
|
86
90
|
// GET
|
|
87
91
|
|
|
88
|
-
const getPermit =
|
|
92
|
+
const getPermit = (chainId: number, account: string, hash: string): Permit | undefined => {
|
|
89
93
|
return permitStore.getPermit(chainId, account, hash);
|
|
90
94
|
};
|
|
91
95
|
|
|
92
|
-
const getPermits =
|
|
96
|
+
const getPermits = (chainId: number, account: string): Record<string, Permit> => {
|
|
93
97
|
return permitStore.getPermits(chainId, account);
|
|
94
98
|
};
|
|
95
99
|
|
|
96
|
-
const getActivePermit =
|
|
100
|
+
const getActivePermit = (chainId: number, account: string): Permit | undefined => {
|
|
97
101
|
return permitStore.getActivePermit(chainId, account);
|
|
98
102
|
};
|
|
99
103
|
|
|
@@ -188,6 +192,7 @@ export const permits = {
|
|
|
188
192
|
getOrCreateSharingPermit,
|
|
189
193
|
|
|
190
194
|
getHash,
|
|
195
|
+
export: exportShared,
|
|
191
196
|
serialize,
|
|
192
197
|
deserialize,
|
|
193
198
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { createCofheClientBase } from '
|
|
3
|
-
import { type CofheClient, type CofheClientConnectionState } from '
|
|
4
|
-
import { createCofheConfigBase, type CofheEnvironment } from '
|
|
5
|
-
import { CofheError, CofheErrorCode } from '
|
|
2
|
+
import { createCofheClientBase } from '../client.js';
|
|
3
|
+
import { type CofheClient, type CofheClientConnectionState } from '../clientTypes.js';
|
|
4
|
+
import { createCofheConfigBase, type CofheEnvironment } from '../config.js';
|
|
5
|
+
import { CofheError, CofheErrorCode } from '../error.js';
|
|
6
6
|
import { type PublicClient, type WalletClient } from 'viem';
|
|
7
|
-
import { EncryptInputsBuilder } from '
|
|
8
|
-
import { Encryptable } from '
|
|
7
|
+
import { EncryptInputsBuilder } from '../encrypt/encryptInputsBuilder.js';
|
|
8
|
+
import { Encryptable } from '../types.js';
|
|
9
9
|
|
|
10
10
|
// Mock dependencies
|
|
11
|
-
vi.mock('
|
|
11
|
+
vi.mock('../keyStore', () => ({
|
|
12
12
|
createKeysStore: vi.fn(() => ({
|
|
13
13
|
rehydrateKeysStore: vi.fn().mockResolvedValue(undefined),
|
|
14
14
|
getFheKey: vi.fn(),
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { FheTypes, verifyDecryptResult, createCofheConfigBase, TASK_MANAGER_ADDRESS } from '@/core';
|
|
2
|
+
import { getChainById } from '@/chains';
|
|
3
|
+
import {
|
|
4
|
+
TEST_PRIVATE_KEY,
|
|
5
|
+
PRIMARY_TEST_CHAIN,
|
|
6
|
+
primaryTestChainRegistry,
|
|
7
|
+
isPrimaryTestChainReady,
|
|
8
|
+
} from '@cofhe/test-setup';
|
|
9
|
+
|
|
10
|
+
import { permits } from '../permits.js';
|
|
11
|
+
import { DecryptForTxBuilder } from '../decrypt/decryptForTxBuilder.js';
|
|
12
|
+
import { DecryptForViewBuilder } from '../decrypt/decryptForViewBuilder.js';
|
|
13
|
+
|
|
14
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
15
|
+
import type { Chain, PublicClient, WalletClient } from 'viem';
|
|
16
|
+
import { createPublicClient, createWalletClient, http, parseAbi } from 'viem';
|
|
17
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
|
+
import { arbitrumSepolia, baseSepolia, sepolia } from 'viem/chains';
|
|
19
|
+
|
|
20
|
+
const account = privateKeyToAccount(TEST_PRIVATE_KEY);
|
|
21
|
+
|
|
22
|
+
const VIEM_CHAINS: Record<number, Chain> = {
|
|
23
|
+
421614: arbitrumSepolia,
|
|
24
|
+
84532: baseSepolia,
|
|
25
|
+
11155111: sepolia,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe('Core – Decrypt Tests', () => {
|
|
29
|
+
let publicClient: PublicClient;
|
|
30
|
+
let walletClient: WalletClient;
|
|
31
|
+
let config: ReturnType<typeof createCofheConfigBase>;
|
|
32
|
+
|
|
33
|
+
let privateCtHash: `0x${string}`;
|
|
34
|
+
let privateValue: bigint;
|
|
35
|
+
|
|
36
|
+
let publicCtHash: `0x${string}`;
|
|
37
|
+
let publicValue: bigint;
|
|
38
|
+
|
|
39
|
+
beforeAll(() => {
|
|
40
|
+
if (!isPrimaryTestChainReady(primaryTestChainRegistry)) {
|
|
41
|
+
throw new Error('Primary test chain registry is not initialized. Run `pnpm test:setup` first.');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const reg = primaryTestChainRegistry;
|
|
45
|
+
const chainId = reg.chainId;
|
|
46
|
+
|
|
47
|
+
const viemChain = VIEM_CHAINS[chainId];
|
|
48
|
+
if (!viemChain) throw new Error(`No viem chain mapping for chain ${chainId}`);
|
|
49
|
+
|
|
50
|
+
const cofheChain = getChainById(chainId);
|
|
51
|
+
if (!cofheChain) throw new Error(`No cofhe chain config for chain ${chainId}`);
|
|
52
|
+
|
|
53
|
+
config = createCofheConfigBase({ supportedChains: [cofheChain] });
|
|
54
|
+
|
|
55
|
+
privateCtHash = reg.privateValue.ctHash as `0x${string}`;
|
|
56
|
+
privateValue = BigInt(reg.privateValue.value);
|
|
57
|
+
|
|
58
|
+
publicCtHash = reg.publicValue.ctHash as `0x${string}`;
|
|
59
|
+
publicValue = BigInt(reg.publicValue.value);
|
|
60
|
+
|
|
61
|
+
publicClient = createPublicClient({ chain: viemChain, transport: http() });
|
|
62
|
+
walletClient = createWalletClient({ chain: viemChain, transport: http(), account });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
function txBuilder(ctHash: `0x${string}`) {
|
|
66
|
+
return new DecryptForTxBuilder({
|
|
67
|
+
config,
|
|
68
|
+
publicClient,
|
|
69
|
+
walletClient,
|
|
70
|
+
chainId: PRIMARY_TEST_CHAIN,
|
|
71
|
+
account: account.address,
|
|
72
|
+
ctHash,
|
|
73
|
+
requireConnected: undefined,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function viewBuilder(ctHash: `0x${string}`, utype: FheTypes) {
|
|
78
|
+
return new DecryptForViewBuilder({
|
|
79
|
+
config,
|
|
80
|
+
publicClient,
|
|
81
|
+
walletClient,
|
|
82
|
+
chainId: PRIMARY_TEST_CHAIN,
|
|
83
|
+
account: account.address,
|
|
84
|
+
ctHash,
|
|
85
|
+
utype,
|
|
86
|
+
requireConnected: undefined,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function createPermit() {
|
|
91
|
+
return permits.createSelf({ issuer: account.address, name: 'Decrypt Test Permit' }, publicClient, walletClient);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// decryptForTx – withoutPermit (global allowance)
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
describe('decryptForTx – withoutPermit (global allowance)', () => {
|
|
99
|
+
it('should decrypt a publicly allowed ciphertext', async () => {
|
|
100
|
+
const result = await txBuilder(publicCtHash).withoutPermit().execute();
|
|
101
|
+
|
|
102
|
+
expect(BigInt(result.ctHash)).toBe(BigInt(publicCtHash));
|
|
103
|
+
expect(result.decryptedValue).toBe(publicValue);
|
|
104
|
+
expect(result.signature).toMatch(/^0x[0-9a-fA-F]+$/);
|
|
105
|
+
}, 180000);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// decryptForTx – withPermit
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
describe('decryptForTx – withPermit', () => {
|
|
113
|
+
it('should decrypt with a self permit', async () => {
|
|
114
|
+
const permit = await createPermit();
|
|
115
|
+
|
|
116
|
+
const result = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
117
|
+
|
|
118
|
+
expect(BigInt(result.ctHash)).toBe(BigInt(privateCtHash));
|
|
119
|
+
expect(result.decryptedValue).toBe(privateValue);
|
|
120
|
+
expect(result.signature).toBeDefined();
|
|
121
|
+
}, 180000);
|
|
122
|
+
|
|
123
|
+
it('should auto-resolve active permit', async () => {
|
|
124
|
+
const permit = await createPermit();
|
|
125
|
+
permits.selectActivePermit(PRIMARY_TEST_CHAIN, account.address, permit.hash);
|
|
126
|
+
|
|
127
|
+
const result = await txBuilder(privateCtHash).withPermit().execute();
|
|
128
|
+
|
|
129
|
+
expect(BigInt(result.ctHash)).toBe(BigInt(privateCtHash));
|
|
130
|
+
expect(result.decryptedValue).toBe(privateValue);
|
|
131
|
+
}, 180000);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
// verifyDecryptResult
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
|
|
138
|
+
describe('verifyDecryptResult', () => {
|
|
139
|
+
it('should verify a valid decrypt result', async () => {
|
|
140
|
+
const permit = await createPermit();
|
|
141
|
+
|
|
142
|
+
const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
143
|
+
|
|
144
|
+
const isValid = await verifyDecryptResult(
|
|
145
|
+
decryptResult.ctHash,
|
|
146
|
+
privateValue,
|
|
147
|
+
decryptResult.signature,
|
|
148
|
+
publicClient
|
|
149
|
+
);
|
|
150
|
+
expect(isValid).toBe(true);
|
|
151
|
+
}, 180000);
|
|
152
|
+
|
|
153
|
+
it('should return false for invalid inputs', async () => {
|
|
154
|
+
const permit = await createPermit();
|
|
155
|
+
|
|
156
|
+
const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
157
|
+
|
|
158
|
+
expect(
|
|
159
|
+
await verifyDecryptResult(decryptResult.ctHash, privateValue + 1n, decryptResult.signature, publicClient)
|
|
160
|
+
).toBe(false);
|
|
161
|
+
}, 180000);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// ---------------------------------------------------------------------------
|
|
165
|
+
// decryptForView
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
describe('decryptForView', () => {
|
|
169
|
+
it('should return the plaintext value', async () => {
|
|
170
|
+
await createPermit();
|
|
171
|
+
|
|
172
|
+
const result = await viewBuilder(privateCtHash, FheTypes.Uint32).execute();
|
|
173
|
+
expect(result).toBe(privateValue);
|
|
174
|
+
}, 180000);
|
|
175
|
+
|
|
176
|
+
it('should agree with decryptForTx on the same handle', async () => {
|
|
177
|
+
const permit = await createPermit();
|
|
178
|
+
|
|
179
|
+
const viewResult = await viewBuilder(privateCtHash, FheTypes.Uint32).execute();
|
|
180
|
+
const txResult = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
181
|
+
|
|
182
|
+
expect(viewResult).toBe(privateValue);
|
|
183
|
+
expect(BigInt(txResult.ctHash)).toBe(BigInt(privateCtHash));
|
|
184
|
+
expect(txResult.decryptedValue).toBe(privateValue);
|
|
185
|
+
}, 180000);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('verifyDecryptResult', () => {
|
|
189
|
+
it('should correctly verify a valid decrypt result', async () => {
|
|
190
|
+
const permit = await createPermit();
|
|
191
|
+
|
|
192
|
+
const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
193
|
+
|
|
194
|
+
const isValid = await verifyDecryptResult(
|
|
195
|
+
decryptResult.ctHash,
|
|
196
|
+
privateValue,
|
|
197
|
+
decryptResult.signature,
|
|
198
|
+
publicClient
|
|
199
|
+
);
|
|
200
|
+
expect(isValid).toBe(true);
|
|
201
|
+
}, 180000);
|
|
202
|
+
|
|
203
|
+
it('should verify identically to the on-chain TaskManager contract', async () => {
|
|
204
|
+
const permit = await createPermit();
|
|
205
|
+
const decryptResult = await txBuilder(privateCtHash).withPermit(permit).execute();
|
|
206
|
+
|
|
207
|
+
const samples = [
|
|
208
|
+
{
|
|
209
|
+
shouldBe: true,
|
|
210
|
+
handle: BigInt(decryptResult.ctHash),
|
|
211
|
+
cleartext: decryptResult.decryptedValue,
|
|
212
|
+
signature: decryptResult.signature,
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
shouldBe: false,
|
|
216
|
+
handle: BigInt(decryptResult.ctHash),
|
|
217
|
+
cleartext: decryptResult.decryptedValue + 1n,
|
|
218
|
+
signature: decryptResult.signature,
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
shouldBe: false,
|
|
222
|
+
handle: BigInt(decryptResult.ctHash) + 1n,
|
|
223
|
+
cleartext: decryptResult.decryptedValue,
|
|
224
|
+
signature: decryptResult.signature,
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
shouldBe: false,
|
|
228
|
+
handle: BigInt(decryptResult.ctHash),
|
|
229
|
+
cleartext: decryptResult.decryptedValue,
|
|
230
|
+
signature: `${decryptResult.signature}00`,
|
|
231
|
+
},
|
|
232
|
+
] as const;
|
|
233
|
+
|
|
234
|
+
for (const sample of samples) {
|
|
235
|
+
const sdkResult = await verifyDecryptResult(sample.handle, sample.cleartext, sample.signature, publicClient);
|
|
236
|
+
|
|
237
|
+
const verifyDecryptResultSafeAbi = parseAbi([
|
|
238
|
+
'function verifyDecryptResultSafe(uint256 ctHash, uint256 cleartext, bytes signature) view returns (bool)',
|
|
239
|
+
]);
|
|
240
|
+
const tmResult = await publicClient.readContract({
|
|
241
|
+
address: TASK_MANAGER_ADDRESS,
|
|
242
|
+
abi: verifyDecryptResultSafeAbi,
|
|
243
|
+
functionName: 'verifyDecryptResultSafe',
|
|
244
|
+
args: [sample.handle, sample.cleartext, sample.signature],
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
expect(sdkResult).to.equal(tmResult);
|
|
248
|
+
expect(sdkResult).to.equal(sample.shouldBe);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
});
|