@cofhe/sdk 0.1.0 → 0.1.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 +48 -0
- package/adapters/ethers5.test.ts +174 -0
- package/adapters/ethers5.ts +36 -0
- package/adapters/ethers6.test.ts +169 -0
- package/adapters/ethers6.ts +36 -0
- package/adapters/hardhat-node.ts +167 -0
- package/adapters/hardhat.hh2.test.ts +159 -0
- package/adapters/hardhat.ts +37 -0
- package/adapters/index.test.ts +25 -0
- package/adapters/index.ts +5 -0
- package/adapters/smartWallet.ts +91 -0
- package/adapters/test-utils.ts +53 -0
- package/adapters/types.ts +6 -0
- package/adapters/wagmi.test.ts +156 -0
- package/adapters/wagmi.ts +17 -0
- package/chains/chains/arbSepolia.ts +14 -0
- package/chains/chains/baseSepolia.ts +14 -0
- package/chains/chains/hardhat.ts +15 -0
- package/chains/chains/sepolia.ts +14 -0
- package/chains/chains.test.ts +49 -0
- package/chains/defineChain.ts +18 -0
- package/chains/index.ts +33 -0
- package/chains/types.ts +32 -0
- package/core/baseBuilder.ts +138 -0
- package/core/client.test.ts +298 -0
- package/core/client.ts +308 -0
- package/core/config.test.ts +224 -0
- package/core/config.ts +213 -0
- package/core/decrypt/MockQueryDecrypterAbi.ts +129 -0
- package/core/decrypt/cofheMocksSealOutput.ts +57 -0
- package/core/decrypt/decryptHandleBuilder.ts +281 -0
- package/core/decrypt/decryptUtils.ts +28 -0
- package/core/decrypt/tnSealOutput.ts +59 -0
- package/core/encrypt/MockZkVerifierAbi.ts +106 -0
- package/core/encrypt/cofheMocksZkVerifySign.ts +278 -0
- package/core/encrypt/encryptInputsBuilder.test.ts +735 -0
- package/core/encrypt/encryptInputsBuilder.ts +512 -0
- package/core/encrypt/encryptUtils.ts +64 -0
- package/core/encrypt/zkPackProveVerify.ts +273 -0
- package/core/error.ts +170 -0
- package/core/fetchKeys.test.ts +212 -0
- package/core/fetchKeys.ts +170 -0
- package/core/index.ts +77 -0
- package/core/keyStore.test.ts +226 -0
- package/core/keyStore.ts +127 -0
- package/core/permits.test.ts +242 -0
- package/core/permits.ts +136 -0
- package/core/result.test.ts +180 -0
- package/core/result.ts +67 -0
- package/core/test-utils.ts +45 -0
- package/core/types.ts +352 -0
- package/core/utils.ts +88 -0
- package/dist/adapters.cjs +88 -0
- package/dist/adapters.d.cts +14558 -0
- package/dist/adapters.d.ts +14558 -0
- package/dist/adapters.js +83 -0
- package/dist/chains.cjs +101 -0
- package/dist/chains.d.cts +99 -0
- package/dist/chains.d.ts +99 -0
- package/dist/chains.js +1 -0
- package/dist/chunk-GZCQQYVI.js +93 -0
- package/dist/chunk-KFGPTJ6X.js +2295 -0
- package/dist/chunk-LU7BMUUT.js +804 -0
- package/dist/core.cjs +3174 -0
- package/dist/core.d.cts +16 -0
- package/dist/core.d.ts +16 -0
- package/dist/core.js +3 -0
- package/dist/node.cjs +3090 -0
- package/dist/node.d.cts +22 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +90 -0
- package/dist/permit-S9CnI6MF.d.cts +333 -0
- package/dist/permit-S9CnI6MF.d.ts +333 -0
- package/dist/permits.cjs +856 -0
- package/dist/permits.d.cts +1056 -0
- package/dist/permits.d.ts +1056 -0
- package/dist/permits.js +1 -0
- package/dist/types-KImPrEIe.d.cts +48 -0
- package/dist/types-KImPrEIe.d.ts +48 -0
- package/dist/types-PhwGgQvs.d.ts +953 -0
- package/dist/types-bB7wLj0q.d.cts +953 -0
- package/dist/web.cjs +3067 -0
- package/dist/web.d.cts +22 -0
- package/dist/web.d.ts +22 -0
- package/dist/web.js +64 -0
- package/node/client.test.ts +152 -0
- package/node/config.test.ts +68 -0
- package/node/encryptInputs.test.ts +175 -0
- package/node/index.ts +96 -0
- package/node/storage.ts +51 -0
- package/package.json +15 -3
- package/permits/index.ts +67 -0
- package/permits/localstorage.test.ts +118 -0
- package/permits/permit.test.ts +474 -0
- package/permits/permit.ts +396 -0
- package/permits/sealing.test.ts +84 -0
- package/permits/sealing.ts +131 -0
- package/permits/signature.ts +79 -0
- package/permits/store.test.ts +128 -0
- package/permits/store.ts +168 -0
- package/permits/test-utils.ts +20 -0
- package/permits/types.ts +174 -0
- package/permits/utils.ts +63 -0
- package/permits/validation.test.ts +288 -0
- package/permits/validation.ts +349 -0
- package/web/client.web.test.ts +152 -0
- package/web/config.web.test.ts +71 -0
- package/web/encryptInputs.web.test.ts +195 -0
- package/web/index.ts +97 -0
- package/web/storage.ts +20 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getAddress } from 'viem';
|
|
2
|
+
import { FheTypes, FheUintUTypes, type UnsealedItem } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export function uint160ToAddress(uint160: bigint): string {
|
|
5
|
+
// Convert bigint to hex string and pad to 20 bytes (40 hex chars)
|
|
6
|
+
const hexStr = uint160.toString(16).padStart(40, '0');
|
|
7
|
+
|
|
8
|
+
// Add 0x prefix and convert to checksum address
|
|
9
|
+
return getAddress('0x' + hexStr);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const isValidUtype = (utype: FheTypes): boolean => {
|
|
13
|
+
return (
|
|
14
|
+
utype === FheTypes.Bool || utype === FheTypes.Uint160 || utype == null || FheUintUTypes.includes(utype as number)
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const convertViaUtype = <U extends FheTypes>(utype: U, value: bigint): UnsealedItem<U> => {
|
|
19
|
+
if (utype === FheTypes.Bool) {
|
|
20
|
+
return !!value as UnsealedItem<U>;
|
|
21
|
+
} else if (utype === FheTypes.Uint160) {
|
|
22
|
+
return uint160ToAddress(value) as UnsealedItem<U>;
|
|
23
|
+
} else if (utype == null || FheUintUTypes.includes(utype as number)) {
|
|
24
|
+
return value as UnsealedItem<U>;
|
|
25
|
+
} else {
|
|
26
|
+
throw new Error(`convertViaUtype :: invalid utype :: ${utype}`);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type Permission, type EthEncryptedData } from '@/permits';
|
|
2
|
+
|
|
3
|
+
import { CofhesdkError, CofhesdkErrorCode } from '../error.js';
|
|
4
|
+
|
|
5
|
+
export async function tnSealOutput(
|
|
6
|
+
ctHash: bigint,
|
|
7
|
+
chainId: number,
|
|
8
|
+
permission: Permission,
|
|
9
|
+
thresholdNetworkUrl: string
|
|
10
|
+
): Promise<EthEncryptedData> {
|
|
11
|
+
let sealed: EthEncryptedData | undefined;
|
|
12
|
+
let errorMessage: string | undefined;
|
|
13
|
+
let sealOutputResult: { sealed: EthEncryptedData; error_message: string } | undefined;
|
|
14
|
+
|
|
15
|
+
const body = {
|
|
16
|
+
ct_tempkey: ctHash.toString(16).padStart(64, '0'),
|
|
17
|
+
host_chain_id: chainId,
|
|
18
|
+
permit: permission,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const sealOutputRes = await fetch(`${thresholdNetworkUrl}/sealoutput`, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
headers: {
|
|
25
|
+
'Content-Type': 'application/json',
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify(body),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
sealOutputResult = (await sealOutputRes.json()) as { sealed: EthEncryptedData; error_message: string };
|
|
31
|
+
sealed = sealOutputResult.sealed;
|
|
32
|
+
errorMessage = sealOutputResult.error_message;
|
|
33
|
+
} catch (e) {
|
|
34
|
+
throw new CofhesdkError({
|
|
35
|
+
code: CofhesdkErrorCode.SealOutputFailed,
|
|
36
|
+
message: `sealOutput request failed`,
|
|
37
|
+
hint: 'Ensure the threshold network URL is valid.',
|
|
38
|
+
cause: e instanceof Error ? e : undefined,
|
|
39
|
+
context: {
|
|
40
|
+
thresholdNetworkUrl,
|
|
41
|
+
body,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (sealed == null) {
|
|
47
|
+
throw new CofhesdkError({
|
|
48
|
+
code: CofhesdkErrorCode.SealOutputReturnedNull,
|
|
49
|
+
message: `sealOutput request returned no data | Caused by: ${errorMessage}`,
|
|
50
|
+
context: {
|
|
51
|
+
thresholdNetworkUrl,
|
|
52
|
+
body,
|
|
53
|
+
sealOutputResult,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return sealed;
|
|
59
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export const MockZkVerifierAbi = [
|
|
2
|
+
{
|
|
3
|
+
type: 'function',
|
|
4
|
+
name: 'exists',
|
|
5
|
+
inputs: [],
|
|
6
|
+
outputs: [{ name: '', type: 'bool', internalType: 'bool' }],
|
|
7
|
+
stateMutability: 'pure',
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
type: 'function',
|
|
11
|
+
name: 'insertCtHash',
|
|
12
|
+
inputs: [
|
|
13
|
+
{ name: 'ctHash', type: 'uint256', internalType: 'uint256' },
|
|
14
|
+
{ name: 'value', type: 'uint256', internalType: 'uint256' },
|
|
15
|
+
],
|
|
16
|
+
outputs: [],
|
|
17
|
+
stateMutability: 'nonpayable',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: 'function',
|
|
21
|
+
name: 'insertPackedCtHashes',
|
|
22
|
+
inputs: [
|
|
23
|
+
{ name: 'ctHashes', type: 'uint256[]', internalType: 'uint256[]' },
|
|
24
|
+
{ name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
|
|
25
|
+
],
|
|
26
|
+
outputs: [],
|
|
27
|
+
stateMutability: 'nonpayable',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: 'function',
|
|
31
|
+
name: 'zkVerify',
|
|
32
|
+
inputs: [
|
|
33
|
+
{ name: 'value', type: 'uint256', internalType: 'uint256' },
|
|
34
|
+
{ name: 'utype', type: 'uint8', internalType: 'uint8' },
|
|
35
|
+
{ name: 'user', type: 'address', internalType: 'address' },
|
|
36
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
37
|
+
{ name: '', type: 'uint256', internalType: 'uint256' },
|
|
38
|
+
],
|
|
39
|
+
outputs: [
|
|
40
|
+
{
|
|
41
|
+
name: '',
|
|
42
|
+
type: 'tuple',
|
|
43
|
+
internalType: 'struct EncryptedInput',
|
|
44
|
+
components: [
|
|
45
|
+
{ name: 'ctHash', type: 'uint256', internalType: 'uint256' },
|
|
46
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
47
|
+
{ name: 'utype', type: 'uint8', internalType: 'uint8' },
|
|
48
|
+
{ name: 'signature', type: 'bytes', internalType: 'bytes' },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
stateMutability: 'nonpayable',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'function',
|
|
56
|
+
name: 'zkVerifyCalcCtHash',
|
|
57
|
+
inputs: [
|
|
58
|
+
{ name: 'value', type: 'uint256', internalType: 'uint256' },
|
|
59
|
+
{ name: 'utype', type: 'uint8', internalType: 'uint8' },
|
|
60
|
+
{ name: 'user', type: 'address', internalType: 'address' },
|
|
61
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
62
|
+
{ name: '', type: 'uint256', internalType: 'uint256' },
|
|
63
|
+
],
|
|
64
|
+
outputs: [{ name: 'ctHash', type: 'uint256', internalType: 'uint256' }],
|
|
65
|
+
stateMutability: 'view',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: 'function',
|
|
69
|
+
name: 'zkVerifyCalcCtHashesPacked',
|
|
70
|
+
inputs: [
|
|
71
|
+
{ name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
|
|
72
|
+
{ name: 'utypes', type: 'uint8[]', internalType: 'uint8[]' },
|
|
73
|
+
{ name: 'user', type: 'address', internalType: 'address' },
|
|
74
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
75
|
+
{ name: 'chainId', type: 'uint256', internalType: 'uint256' },
|
|
76
|
+
],
|
|
77
|
+
outputs: [{ name: 'ctHashes', type: 'uint256[]', internalType: 'uint256[]' }],
|
|
78
|
+
stateMutability: 'view',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: 'function',
|
|
82
|
+
name: 'zkVerifyPacked',
|
|
83
|
+
inputs: [
|
|
84
|
+
{ name: 'values', type: 'uint256[]', internalType: 'uint256[]' },
|
|
85
|
+
{ name: 'utypes', type: 'uint8[]', internalType: 'uint8[]' },
|
|
86
|
+
{ name: 'user', type: 'address', internalType: 'address' },
|
|
87
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
88
|
+
{ name: 'chainId', type: 'uint256', internalType: 'uint256' },
|
|
89
|
+
],
|
|
90
|
+
outputs: [
|
|
91
|
+
{
|
|
92
|
+
name: 'inputs',
|
|
93
|
+
type: 'tuple[]',
|
|
94
|
+
internalType: 'struct EncryptedInput[]',
|
|
95
|
+
components: [
|
|
96
|
+
{ name: 'ctHash', type: 'uint256', internalType: 'uint256' },
|
|
97
|
+
{ name: 'securityZone', type: 'uint8', internalType: 'uint8' },
|
|
98
|
+
{ name: 'utype', type: 'uint8', internalType: 'uint8' },
|
|
99
|
+
{ name: 'signature', type: 'bytes', internalType: 'bytes' },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
stateMutability: 'nonpayable',
|
|
104
|
+
},
|
|
105
|
+
{ type: 'error', name: 'InvalidInputs', inputs: [] },
|
|
106
|
+
] as const;
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { type EncryptableItem, FheTypes } from '../types.js';
|
|
2
|
+
import { MAX_ENCRYPTABLE_BITS, type VerifyResult } from './zkPackProveVerify.js';
|
|
3
|
+
import {
|
|
4
|
+
createWalletClient,
|
|
5
|
+
http,
|
|
6
|
+
encodePacked,
|
|
7
|
+
keccak256,
|
|
8
|
+
hashMessage,
|
|
9
|
+
toBytes,
|
|
10
|
+
type PublicClient,
|
|
11
|
+
type WalletClient,
|
|
12
|
+
} from 'viem';
|
|
13
|
+
import { MockZkVerifierAbi } from './MockZkVerifierAbi.js';
|
|
14
|
+
import { hardhat } from 'viem/chains';
|
|
15
|
+
import { CofhesdkError, CofhesdkErrorCode } from '../error.js';
|
|
16
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
17
|
+
|
|
18
|
+
// Address the Mock ZkVerifier contract is deployed to on the Hardhat chain
|
|
19
|
+
export const MocksZkVerifierAddress = '0x0000000000000000000000000000000000000100';
|
|
20
|
+
// Private key of the account expected to sign the encrypted inputs
|
|
21
|
+
export const MocksEncryptedInputSignerPkey = '0x6c8d7f768a6bb4aafe85e8a2f5a9680355239c7e14646ed62b044e39de154512';
|
|
22
|
+
|
|
23
|
+
type EncryptableItemWithCtHash = EncryptableItem & {
|
|
24
|
+
ctHash: bigint;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The mocks don't use a tfhe builder, so we check the encryptable bits here to preserve parity
|
|
29
|
+
*/
|
|
30
|
+
export async function cofheMocksCheckEncryptableBits(items: EncryptableItem[]): Promise<void> {
|
|
31
|
+
let totalBits = 0;
|
|
32
|
+
for (const item of items) {
|
|
33
|
+
switch (item.utype) {
|
|
34
|
+
case FheTypes.Bool: {
|
|
35
|
+
totalBits += 1;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case FheTypes.Uint8: {
|
|
39
|
+
totalBits += 8;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
case FheTypes.Uint16: {
|
|
43
|
+
totalBits += 16;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case FheTypes.Uint32: {
|
|
47
|
+
totalBits += 32;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case FheTypes.Uint64: {
|
|
51
|
+
totalBits += 64;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case FheTypes.Uint128: {
|
|
55
|
+
totalBits += 128;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
// [U256-DISABLED]
|
|
59
|
+
// case FheTypes.Uint256: {
|
|
60
|
+
// totalBits += 256;
|
|
61
|
+
// break;
|
|
62
|
+
// }
|
|
63
|
+
case FheTypes.Uint160: {
|
|
64
|
+
totalBits += 160;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (totalBits > MAX_ENCRYPTABLE_BITS) {
|
|
70
|
+
throw new CofhesdkError({
|
|
71
|
+
code: CofhesdkErrorCode.ZkPackFailed,
|
|
72
|
+
message: `Total bits ${totalBits} exceeds ${MAX_ENCRYPTABLE_BITS}`,
|
|
73
|
+
hint: `Ensure that the total bits of the items to encrypt does not exceed ${MAX_ENCRYPTABLE_BITS}`,
|
|
74
|
+
context: {
|
|
75
|
+
totalBits,
|
|
76
|
+
maxBits: MAX_ENCRYPTABLE_BITS,
|
|
77
|
+
items,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* In the mocks context, we use the MockZkVerifier contract to calculate the ctHashes.
|
|
85
|
+
*/
|
|
86
|
+
async function calcCtHashes(
|
|
87
|
+
items: EncryptableItem[],
|
|
88
|
+
account: string,
|
|
89
|
+
securityZone: number,
|
|
90
|
+
publicClient: PublicClient
|
|
91
|
+
): Promise<EncryptableItemWithCtHash[]> {
|
|
92
|
+
const calcCtHashesArgs = [
|
|
93
|
+
items.map(({ data }) => BigInt(data)),
|
|
94
|
+
items.map(({ utype }) => utype),
|
|
95
|
+
account as `0x${string}`,
|
|
96
|
+
securityZone,
|
|
97
|
+
BigInt(hardhat.id),
|
|
98
|
+
] as const;
|
|
99
|
+
|
|
100
|
+
let ctHashes: bigint[];
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
ctHashes = (await publicClient.readContract({
|
|
104
|
+
address: MocksZkVerifierAddress,
|
|
105
|
+
abi: MockZkVerifierAbi,
|
|
106
|
+
functionName: 'zkVerifyCalcCtHashesPacked',
|
|
107
|
+
args: calcCtHashesArgs,
|
|
108
|
+
})) as bigint[];
|
|
109
|
+
} catch (err) {
|
|
110
|
+
throw new CofhesdkError({
|
|
111
|
+
code: CofhesdkErrorCode.ZkMocksCalcCtHashesFailed,
|
|
112
|
+
message: `mockZkVerifySign calcCtHashes failed while calling zkVerifyCalcCtHashesPacked`,
|
|
113
|
+
cause: err instanceof Error ? err : undefined,
|
|
114
|
+
context: {
|
|
115
|
+
address: MocksZkVerifierAddress,
|
|
116
|
+
items,
|
|
117
|
+
account,
|
|
118
|
+
securityZone,
|
|
119
|
+
publicClient,
|
|
120
|
+
calcCtHashesArgs,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (ctHashes.length !== items.length) {
|
|
126
|
+
throw new CofhesdkError({
|
|
127
|
+
code: CofhesdkErrorCode.ZkMocksCalcCtHashesFailed,
|
|
128
|
+
message: `mockZkVerifySign calcCtHashes returned incorrect number of ctHashes`,
|
|
129
|
+
context: {
|
|
130
|
+
items,
|
|
131
|
+
account,
|
|
132
|
+
securityZone,
|
|
133
|
+
publicClient,
|
|
134
|
+
calcCtHashesArgs,
|
|
135
|
+
ctHashes,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return items.map((item, index) => ({
|
|
141
|
+
...item,
|
|
142
|
+
ctHash: ctHashes[index],
|
|
143
|
+
}));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Insert the calculated ctHashes into the MockZkVerifier contract along with the plaintext values.
|
|
148
|
+
* The plaintext values are used on chain to simulate the true FHE operations.
|
|
149
|
+
*/
|
|
150
|
+
async function insertCtHashes(items: EncryptableItemWithCtHash[], walletClient: WalletClient): Promise<void> {
|
|
151
|
+
const insertPackedCtHashesArgs = [items.map(({ ctHash }) => ctHash), items.map(({ data }) => BigInt(data))] as const;
|
|
152
|
+
try {
|
|
153
|
+
const account = walletClient.account!;
|
|
154
|
+
|
|
155
|
+
await walletClient.writeContract({
|
|
156
|
+
address: MocksZkVerifierAddress,
|
|
157
|
+
abi: MockZkVerifierAbi,
|
|
158
|
+
functionName: 'insertPackedCtHashes',
|
|
159
|
+
args: insertPackedCtHashesArgs,
|
|
160
|
+
chain: hardhat,
|
|
161
|
+
account: account,
|
|
162
|
+
});
|
|
163
|
+
} catch (err) {
|
|
164
|
+
throw new CofhesdkError({
|
|
165
|
+
code: CofhesdkErrorCode.ZkMocksInsertCtHashesFailed,
|
|
166
|
+
message: `mockZkVerifySign insertPackedCtHashes failed while calling insertPackedCtHashes`,
|
|
167
|
+
cause: err instanceof Error ? err : undefined,
|
|
168
|
+
context: {
|
|
169
|
+
items,
|
|
170
|
+
walletClient,
|
|
171
|
+
insertPackedCtHashesArgs,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The mocks verify the EncryptedInputs' signature against the known proof signer account.
|
|
179
|
+
* Locally, we create the proof signatures from the known proof signer account.
|
|
180
|
+
*/
|
|
181
|
+
async function createProofSignatures(items: EncryptableItemWithCtHash[], securityZone: number): Promise<string[]> {
|
|
182
|
+
let signatures: string[] = [];
|
|
183
|
+
|
|
184
|
+
// Create wallet client for the encrypted input signer
|
|
185
|
+
// This wallet won't send a transaction, so gas isn't needed
|
|
186
|
+
// This wallet doesn't need to be connected to the network
|
|
187
|
+
let encInputSignerClient: WalletClient | undefined;
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
encInputSignerClient = createWalletClient({
|
|
191
|
+
chain: hardhat,
|
|
192
|
+
transport: http(),
|
|
193
|
+
account: privateKeyToAccount(MocksEncryptedInputSignerPkey),
|
|
194
|
+
});
|
|
195
|
+
} catch (err) {
|
|
196
|
+
throw new CofhesdkError({
|
|
197
|
+
code: CofhesdkErrorCode.ZkMocksCreateProofSignatureFailed,
|
|
198
|
+
message: `mockZkVerifySign createProofSignatures failed while creating wallet client`,
|
|
199
|
+
cause: err instanceof Error ? err : undefined,
|
|
200
|
+
context: {
|
|
201
|
+
MocksEncryptedInputSignerPkey,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
try {
|
|
207
|
+
for (const item of items) {
|
|
208
|
+
// Pack the data into bytes and hash it
|
|
209
|
+
const packedData = encodePacked(['uint256', 'int32', 'uint8'], [BigInt(item.data), securityZone, item.utype]);
|
|
210
|
+
const messageHash = keccak256(packedData);
|
|
211
|
+
|
|
212
|
+
// Convert to EthSignedMessageHash (adds "\x19Ethereum Signed Message:\n32" prefix)
|
|
213
|
+
const ethSignedHash = hashMessage({ raw: toBytes(messageHash) });
|
|
214
|
+
|
|
215
|
+
// Sign the message
|
|
216
|
+
const signature = await encInputSignerClient.signMessage({
|
|
217
|
+
message: { raw: toBytes(ethSignedHash) },
|
|
218
|
+
account: encInputSignerClient.account!,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
signatures.push(signature);
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
throw new CofhesdkError({
|
|
225
|
+
code: CofhesdkErrorCode.ZkMocksCreateProofSignatureFailed,
|
|
226
|
+
message: `mockZkVerifySign createProofSignatures failed while calling signMessage`,
|
|
227
|
+
cause: err instanceof Error ? err : undefined,
|
|
228
|
+
context: {
|
|
229
|
+
items,
|
|
230
|
+
securityZone,
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (signatures.length !== items.length) {
|
|
236
|
+
throw new CofhesdkError({
|
|
237
|
+
code: CofhesdkErrorCode.ZkMocksCreateProofSignatureFailed,
|
|
238
|
+
message: `mockZkVerifySign createProofSignatures returned incorrect number of signatures`,
|
|
239
|
+
context: {
|
|
240
|
+
items,
|
|
241
|
+
securityZone,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return signatures;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Transforms the encryptable items into EncryptedInputs ready to be used in a transaction on the hardhat chain.
|
|
251
|
+
* The EncryptedInputs are returned in the same format as from CoFHE, and include on-chain verifiable signatures.
|
|
252
|
+
*/
|
|
253
|
+
export async function cofheMocksZkVerifySign(
|
|
254
|
+
items: EncryptableItem[],
|
|
255
|
+
account: string,
|
|
256
|
+
securityZone: number,
|
|
257
|
+
publicClient: PublicClient,
|
|
258
|
+
walletClient: WalletClient,
|
|
259
|
+
zkvWalletClient: WalletClient | undefined
|
|
260
|
+
): Promise<VerifyResult[]> {
|
|
261
|
+
// Use config.mocks.zkvWalletClient if provided, otherwise use connected walletClient
|
|
262
|
+
const _walletClient = zkvWalletClient ?? walletClient;
|
|
263
|
+
|
|
264
|
+
// Call MockZkVerifier contract to calculate the ctHashes
|
|
265
|
+
const encryptableItems = await calcCtHashes(items, account, securityZone, publicClient);
|
|
266
|
+
|
|
267
|
+
// Insert the ctHashes into the MockZkVerifier contract
|
|
268
|
+
await insertCtHashes(encryptableItems, _walletClient);
|
|
269
|
+
|
|
270
|
+
// Locally create the proof signatures from the known proof signer account
|
|
271
|
+
const signatures = await createProofSignatures(encryptableItems, securityZone);
|
|
272
|
+
|
|
273
|
+
// Return the ctHashes and signatures in the same format as CoFHE
|
|
274
|
+
return encryptableItems.map((item, index) => ({
|
|
275
|
+
ct_hash: item.ctHash.toString(),
|
|
276
|
+
signature: signatures[index],
|
|
277
|
+
}));
|
|
278
|
+
}
|