@inco/js 0.1.31 → 0.1.33

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.
Files changed (102) hide show
  1. package/README.md +28 -57
  2. package/dist/binary.js +67 -0
  3. package/dist/chain.js +24 -0
  4. package/dist/encryption/encryption.js +98 -0
  5. package/dist/encryption/index.cjs +132 -123
  6. package/dist/encryption/index.js +2 -0
  7. package/dist/encryption/index.mjs +132 -123
  8. package/dist/fhevm/fhe-environment.js +8 -0
  9. package/dist/fhevm/fhevm.js +139 -0
  10. package/dist/fhevm/index.js +2 -0
  11. package/dist/fhevm/reencrypt.js +123 -0
  12. package/dist/fhevm/tfhe.js +324 -0
  13. package/dist/fhevm/types.js +26 -0
  14. package/dist/generated/abis/addTwo.js +59 -0
  15. package/dist/generated/abis/inco-fhevm.js +6242 -0
  16. package/dist/generated/abis/index.js +3 -0
  17. package/dist/generated/abis/lightning.js +12489 -0
  18. package/dist/generated/es/cosmos/ics23/v1/proofs_pb.js +198 -0
  19. package/dist/generated/es/cosmos/msg/v1/msg_pb.js +33 -0
  20. package/dist/generated/es/cosmos_proto/cosmos_pb.js +115 -0
  21. package/dist/generated/es/google/api/annotations_pb.js +27 -0
  22. package/dist/generated/es/google/api/http_pb.js +34 -0
  23. package/dist/generated/es/inco/fhe/v1/events_pb.js +21 -0
  24. package/dist/generated/es/inco/fhe/v1/genesis_pb.js +46 -0
  25. package/dist/generated/es/inco/fhe/v1/query_pb.js +108 -0
  26. package/dist/generated/es/inco/fhe/v1/tx_pb.js +108 -0
  27. package/dist/generated/es/inco/fhe/v1/types_pb.js +133 -0
  28. package/dist/generated/es/inco/kms/lite/v1/kms_service_pb.js +43 -0
  29. package/dist/generated/es/inco/kms/lite/v1/types_pb.js +44 -0
  30. package/dist/generated/es/inco/preflight/v1/genesis_pb.js +20 -0
  31. package/dist/generated/es/inco/preflight/v1/query_pb.js +38 -0
  32. package/dist/generated/es/inco/preflight/v1/tx_pb.js +48 -0
  33. package/dist/generated/es/inco/preflight/v1/types_pb.js +34 -0
  34. package/dist/generated/es/kms/base_pb.js +238 -0
  35. package/dist/generated/es/sf/ethereum/type/v2/type_pb.js +571 -0
  36. package/dist/generated/fhe-environments.js +15 -0
  37. package/dist/generated/lightning.js +399 -0
  38. package/dist/generated/local-node.js +8 -0
  39. package/dist/generated/ts/amino/amino.js +8 -0
  40. package/dist/generated/ts/cometbft/abci/v1/types.js +5063 -0
  41. package/dist/generated/ts/cometbft/crypto/v1/keys.js +105 -0
  42. package/dist/generated/ts/cometbft/crypto/v1/proof.js +430 -0
  43. package/dist/generated/ts/cometbft/types/v1/params.js +713 -0
  44. package/dist/generated/ts/cometbft/types/v1/validator.js +353 -0
  45. package/dist/generated/ts/cosmos/app/v1alpha1/module.js +218 -0
  46. package/dist/generated/ts/cosmos/msg/v1/msg.js +8 -0
  47. package/dist/generated/ts/cosmos_proto/cosmos.js +211 -0
  48. package/dist/generated/ts/gogoproto/gogo.js +8 -0
  49. package/dist/generated/ts/google/api/annotations.js +8 -0
  50. package/dist/generated/ts/google/api/http.js +353 -0
  51. package/dist/generated/ts/google/protobuf/descriptor.js +5070 -0
  52. package/dist/generated/ts/google/protobuf/duration.js +90 -0
  53. package/dist/generated/ts/google/protobuf/timestamp.js +90 -0
  54. package/dist/generated/ts/google/protobuf/wrappers.js +506 -0
  55. package/dist/generated/ts/inco/abci/v1/types.js +70 -0
  56. package/dist/generated/ts/inco/fhe/module/v1/module.js +63 -0
  57. package/dist/generated/ts/inco/fhe/v1/events.js +187 -0
  58. package/dist/generated/ts/inco/fhe/v1/genesis.js +711 -0
  59. package/dist/generated/ts/inco/fhe/v1/query.js +1391 -0
  60. package/dist/generated/ts/inco/fhe/v1/tx.js +1233 -0
  61. package/dist/generated/ts/inco/fhe/v1/types.js +985 -0
  62. package/dist/generated/ts/inco/originchain/module/v1/module.js +63 -0
  63. package/dist/generated/ts/inco/originchain/v1/abci.js +328 -0
  64. package/dist/generated/ts/inco/originchain/v1/events.js +213 -0
  65. package/dist/generated/ts/inco/originchain/v1/genesis.js +66 -0
  66. package/dist/generated/ts/inco/originchain/v1/query.js +277 -0
  67. package/dist/generated/ts/inco/originchain/v1/tx.js +137 -0
  68. package/dist/generated/ts/inco/originchain/v1/types.js +200 -0
  69. package/dist/generated/ts/inco/preflight/module/v1/module.js +63 -0
  70. package/dist/generated/ts/inco/preflight/v1/genesis.js +182 -0
  71. package/dist/generated/ts/inco/preflight/v1/query.js +256 -0
  72. package/dist/generated/ts/inco/preflight/v1/tx.js +445 -0
  73. package/dist/generated/ts/inco/preflight/v1/types.js +395 -0
  74. package/dist/handle.js +94 -0
  75. package/dist/index.cjs +140 -131
  76. package/dist/index.js +6 -0
  77. package/dist/index.mjs +140 -131
  78. package/dist/l1/client.js +93 -0
  79. package/dist/l1/index.js +3 -0
  80. package/dist/l1/preflight.js +39 -0
  81. package/dist/lite/deployments.js +17 -0
  82. package/dist/lite/ecies.js +124 -0
  83. package/dist/lite/hadu.js +36 -0
  84. package/dist/lite/index.cjs +186 -146
  85. package/dist/lite/index.js +7 -0
  86. package/dist/lite/index.mjs +3890 -3788
  87. package/dist/lite/lightning.js +179 -0
  88. package/dist/lite/reencrypt.d.ts +1 -0
  89. package/dist/lite/reencrypt.js +148 -0
  90. package/dist/local/index.cjs +25 -2573
  91. package/dist/local/index.js +2 -0
  92. package/dist/local/index.mjs +5352 -7837
  93. package/dist/local/local-node.js +24 -0
  94. package/dist/reencryption/eip712.js +81 -0
  95. package/dist/reencryption/index.cjs +132 -123
  96. package/dist/reencryption/index.js +3 -0
  97. package/dist/reencryption/index.mjs +132 -123
  98. package/dist/reencryption/types.js +2 -0
  99. package/dist/schema.js +15 -0
  100. package/dist/viem.d.ts +53 -52
  101. package/dist/viem.js +8 -0
  102. package/package.json +11 -48
@@ -0,0 +1,139 @@
1
+ import { createClient } from '@connectrpc/connect';
2
+ import { createGrpcTransport } from '@connectrpc/connect-node';
3
+ import { createPublicClient, createWalletClient, getContract, http, } from 'viem';
4
+ import { privateKeyToAccount } from 'viem/accounts';
5
+ import * as chains from 'viem/chains';
6
+ import { normaliseToHex } from '../binary';
7
+ import { gatewayContractAbi, kmsVerifierAbi } from '../generated/abis/inco-fhevm';
8
+ import { Query } from '../generated/es/inco/fhe/v1/query_pb';
9
+ import { createL1Client, createL1Wallet } from '../l1';
10
+ import { getFheEnvironment } from './fhe-environment';
11
+ // Create a public and wallet client for the given chain.
12
+ export function createPublicWalletClient({ account, hostChainRpcUrl, chain, }) {
13
+ const transport = http(hostChainRpcUrl);
14
+ const publicClient = createPublicClient({
15
+ chain,
16
+ transport,
17
+ });
18
+ // const privateKey = await shell("cast wallet private-key --account sepolia_deployer --password ''");
19
+ // const account = privateKeyToAccount(mustBeHex(privateKey));
20
+ const walletClient = createWalletClient({
21
+ chain,
22
+ transport,
23
+ account,
24
+ });
25
+ return { public: publicClient, wallet: walletClient };
26
+ }
27
+ export function getFhevmDeployerClient({ deployer, hostChainRpcUrl, chain, }) {
28
+ const viemChain = getViemChain(chain.id);
29
+ const transport = http(hostChainRpcUrl);
30
+ const publicClient = createPublicClient({
31
+ chain: viemChain,
32
+ transport,
33
+ });
34
+ // const privateKey = await shell("cast wallet private-key --account sepolia_deployer --password ''");
35
+ // const account = privateKeyToAccount(mustBeHex(privateKey));
36
+ const walletClient = createWalletClient({
37
+ chain: viemChain,
38
+ transport,
39
+ account: deployer,
40
+ });
41
+ return { public: publicClient, wallet: walletClient };
42
+ }
43
+ export async function configureFhevmContracts({ chain, hostChain: { privateKeys, rpcUrl }, }) {
44
+ const deployer = privateKeyToAccount(normaliseToHex(privateKeys.deployer));
45
+ const relayer = privateKeyToAccount(normaliseToHex(privateKeys.relayer));
46
+ const kmsSigner = privateKeyToAccount(normaliseToHex(privateKeys.kmsSigner));
47
+ console.log(`Configuring FHE environment contracts on ${chain.name} with deployer ${deployer.address}, relayer ${relayer.address}, and KMS signer ${kmsSigner.address}...`);
48
+ const client = getFhevmDeployerClient({
49
+ hostChainRpcUrl: rpcUrl,
50
+ deployer,
51
+ chain,
52
+ });
53
+ const { gatewayAddress, kmsVerifierAddress } = getFheEnvironment(chain.id);
54
+ const gateway = getContract({
55
+ address: gatewayAddress,
56
+ abi: gatewayContractAbi,
57
+ client,
58
+ });
59
+ const kmsVerifier = getContract({
60
+ address: kmsVerifierAddress,
61
+ abi: kmsVerifierAbi,
62
+ client,
63
+ });
64
+ console.log(`Adding relayer ${relayer.address}...`);
65
+ let addRelayerTxReceipt = null;
66
+ let addKmsSignerTxReceipt = null;
67
+ const ErrAlreadyRelayer = 'Address is already relayer';
68
+ try {
69
+ const addRelayerTxHash = await gateway.write.addRelayer([relayer.address]);
70
+ addRelayerTxReceipt = await client.public.waitForTransactionReceipt({
71
+ hash: addRelayerTxHash,
72
+ });
73
+ }
74
+ catch (err) {
75
+ if (!err.message.includes(ErrAlreadyRelayer)) {
76
+ throw err;
77
+ }
78
+ console.log(`Relayer ${relayer.address} already added`);
79
+ }
80
+ console.log(`Adding KMS signer ${kmsSigner.address}...`);
81
+ const ErrAlreadySigner = 'Address is already a signer';
82
+ try {
83
+ const addKmsSignerTxHash = await kmsVerifier.write.addSigner([kmsSigner.address]);
84
+ addKmsSignerTxReceipt = await client.public.waitForTransactionReceipt({
85
+ hash: addKmsSignerTxHash,
86
+ });
87
+ }
88
+ catch (err) {
89
+ if (!err.message.includes(ErrAlreadySigner)) {
90
+ throw err;
91
+ }
92
+ console.log(`KMS signer ${kmsSigner.address} already added`);
93
+ }
94
+ return { addRelayerTxReceipt, addKmsSignerTxReceipt };
95
+ }
96
+ // Attempts to ensure the given Inco L1 has the FHE environment for the given chain/ACL registered.
97
+ // based extracting from logs.
98
+ export async function ensureFheEnvironmentRegistered({ l1, chain, }) {
99
+ console.log(`Ensuring FHE environment is registered on ${l1.grpcEndpoint} ...`);
100
+ const { aclAddress } = getFheEnvironment(chain.id);
101
+ const wallet = await createL1Wallet(l1.mnemonic);
102
+ const signingClient = await createL1Client({
103
+ cometRpcEndpoint: l1.cometRpcEndpoint,
104
+ grpcEndpoint: l1.grpcEndpoint,
105
+ wallet,
106
+ });
107
+ const transport = createGrpcTransport({ baseUrl: l1.grpcEndpoint });
108
+ const queryClient = createClient(Query, transport);
109
+ const [signingAccount] = await wallet.getAccounts();
110
+ const fheEnvArg = {
111
+ keysetId: aclAddress.slice(2),
112
+ hostChainId: `evm/${chain.id}`,
113
+ accessControl: undefined,
114
+ };
115
+ const NotFoundErrorMessage = 'collections: not found';
116
+ try {
117
+ const { fheEnv } = await queryClient.fheEnv(fheEnvArg);
118
+ console.log(`FHE environment already registered on ${chain.id} using ACL ${aclAddress} : ${JSON.stringify(fheEnv)} `);
119
+ }
120
+ catch (err) {
121
+ if (String(err).includes(NotFoundErrorMessage)) {
122
+ const tx = await signingClient.sendTx(signingAccount.address, '/inco.fhe.v1.MsgAddFheEnv', {
123
+ fheEnv: fheEnvArg,
124
+ authority: signingAccount.address,
125
+ });
126
+ console.log(tx);
127
+ return;
128
+ }
129
+ throw err;
130
+ }
131
+ }
132
+ function getViemChain(chainId) {
133
+ const found = Object.values(chains).find((chain) => chain.id === chainId);
134
+ if (!found) {
135
+ throw new Error(`could not find chain with id ${chainId}`);
136
+ }
137
+ return found;
138
+ }
139
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmhldm0uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmhldm0vZmhldm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQy9ELE9BQU8sRUFHTCxrQkFBa0IsRUFDbEIsa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxJQUFJLEdBS0wsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEQsT0FBTyxLQUFLLE1BQU0sTUFBTSxhQUFhLENBQUM7QUFDdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUUzQyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsY0FBYyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzdELE9BQU8sRUFBRSxjQUFjLEVBQUUsY0FBYyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBT3RELHlEQUF5RDtBQUN6RCxNQUFNLFVBQVUsd0JBQXdCLENBQUMsRUFDdkMsT0FBTyxFQUNQLGVBQWUsRUFDZixLQUFLLEdBS047SUFDQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDeEMsTUFBTSxZQUFZLEdBQUcsa0JBQWtCLENBQTRCO1FBQ2pFLEtBQUs7UUFDTCxTQUFTO0tBQ1YsQ0FBQyxDQUFDO0lBQ0gsc0dBQXNHO0lBQ3RHLDhEQUE4RDtJQUM5RCxNQUFNLFlBQVksR0FBRyxrQkFBa0IsQ0FBQztRQUN0QyxLQUFLO1FBQ0wsU0FBUztRQUNULE9BQU87S0FDUixDQUFDLENBQUM7SUFFSCxPQUFPLEVBQUUsTUFB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
@@ -0,0 +1,2 @@
1
+ export * from './fhe-environment';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmhldm0vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxtQkFBbUIsQ0FBQyJ9
@@ -0,0 +1,123 @@
1
+ import { Schema } from 'effect';
2
+ import { cryptobox_get_pk, cryptobox_keygen, cryptobox_pk_to_u8vec, cryptobox_sk_to_u8vec, new_client, process_reencryption_resp_from_js, u8vec_to_cryptobox_pk, u8vec_to_cryptobox_sk, } from 'node-tkms';
3
+ import { getAddress, hexToBigInt } from 'viem';
4
+ import { bytesToBigInt, bytesToHex } from '../binary';
5
+ import { bigintToPlaintext, encryptionSchemes, } from '../encryption/encryption';
6
+ import { getHandleType } from '../handle';
7
+ import { createEIP712Payload } from '../reencryption';
8
+ import { parse } from '../schema';
9
+ // The domain constants that Zama uses for reencrypts.
10
+ const ZAMA_REENCRYPT_DOMAIN = {
11
+ name: 'Authorization token',
12
+ version: '1',
13
+ salt: undefined,
14
+ };
15
+ export async function zamaReencryptor({ chainId, gatewayUrl, walletClient, unsafeSkipVerifyKMSSignatures, contractAddress, kmsSigners, userAddress, }) {
16
+ const ephemeralKeypair = generateCryptoBoxEphemeralKeyPair();
17
+ // Sign the EIP712 attesting that the user has access to the private key
18
+ // corresponding to the ephemeral public key.
19
+ const eip712Payload = createEIP712Payload({
20
+ chainId,
21
+ primaryType: 'ReencryptionRequest',
22
+ primaryTypeFields: [{ name: 'publicKey', type: 'bytes' }],
23
+ message: {
24
+ publicKey: bytesToHex(ephemeralKeypair.encodePublicKey()),
25
+ },
26
+ domainName: ZAMA_REENCRYPT_DOMAIN.name,
27
+ domainVersion: ZAMA_REENCRYPT_DOMAIN.version,
28
+ });
29
+ // Using browser extensions, this step will prompt the user to sign the
30
+ // payload.
31
+ const eip712Signature = await walletClient.signTypedData(eip712Payload);
32
+ return async function reencrypt({ handle, }) {
33
+ const handleBigInt = hexToBigInt(handle);
34
+ const reencryptRequest = {
35
+ signature: eip712Signature.replace(/^(0x)/, ''),
36
+ client_address: getAddress(userAddress),
37
+ enc_key: bytesToHex(ephemeralKeypair.encodePublicKey()).replace(/^(0x)/, ''),
38
+ ciphertext_handle: handleBigInt.toString(16).padStart(64, '0'),
39
+ eip712_verifying_contract: getAddress(contractAddress),
40
+ };
41
+ const reencryptResponse = await makeReencryptRequest(reencryptRequest, gatewayUrl);
42
+ let pubKey;
43
+ let privKey;
44
+ try {
45
+ pubKey = u8vec_to_cryptobox_pk(ephemeralKeypair.publicKey);
46
+ privKey = u8vec_to_cryptobox_sk(ephemeralKeypair.privateKey);
47
+ }
48
+ catch (e) {
49
+ throw new Error(`Invalid public or private key: ${JSON.stringify(e)}`);
50
+ }
51
+ const client = new_client(kmsSigners, userAddress, 'default');
52
+ try {
53
+ const buffer = new ArrayBuffer(32);
54
+ const view = new DataView(buffer);
55
+ view.setUint32(28, Number(chainId), false);
56
+ const chainIdArrayBE = new Uint8Array(buffer);
57
+ // Duplicate reencryptRequest and replace ciphertext_handle with ciphertext_digest.
58
+ const { ciphertext_handle, ...p } = reencryptRequest;
59
+ // TODO (from Zama): check all ciphertext digests are all the same
60
+ const payloadForVerification = {
61
+ ...p,
62
+ ciphertext_digest: reencryptResponse.response[0].ciphertext_digest,
63
+ };
64
+ const decrypted = process_reencryption_resp_from_js(client, payloadForVerification, {
65
+ name: eip712Payload.domain.name,
66
+ version: eip712Payload.domain.version,
67
+ chain_id: chainIdArrayBE,
68
+ verifying_contract: eip712Payload.domain.verifyingContract,
69
+ }, reencryptResponse.response, pubKey, privKey, !unsafeSkipVerifyKMSSignatures);
70
+ return bigintToPlaintext(encryptionSchemes.cryptobox, getHandleType(handle), bytesToBigInt(decrypted));
71
+ }
72
+ catch (e) {
73
+ console.error(e);
74
+ throw new Error(`An error occurred during decryption: ${e}`);
75
+ }
76
+ };
77
+ }
78
+ // Generate a new ephemeral keypair for reencryption.
79
+ export function generateCryptoBoxEphemeralKeyPair() {
80
+ const keypair = cryptobox_keygen();
81
+ const publicKey = cryptobox_pk_to_u8vec(cryptobox_get_pk(keypair));
82
+ return {
83
+ scheme: encryptionSchemes.cryptobox,
84
+ publicKey,
85
+ privateKey: cryptobox_sk_to_u8vec(keypair),
86
+ encodePublicKey() {
87
+ return publicKey;
88
+ },
89
+ };
90
+ }
91
+ // This is the response type of the reencrypt endpoint, defined on the
92
+ // server-side in Zama's gateway. The response field is a vector of this struct
93
+ // in Rust:
94
+ // https://github.com/zama-ai/kms-core/blob/a3b824b389e87429d04537696e28dee902a3b2d9/blockchain/events/src/kms.rs#L985-L1003
95
+ const ZamaGatewayReencryptResponse = Schema.Struct({
96
+ status: Schema.Union(Schema.Literal('success'), Schema.Literal('failure')),
97
+ response: Schema.Array(Schema.Struct({
98
+ ciphertext_digest: Schema.optional(Schema.String),
99
+ payload: Schema.String,
100
+ signature: Schema.String,
101
+ })),
102
+ });
103
+ // Make a HTTP request to the reencrypt endpoint of the gateway.
104
+ async function makeReencryptRequest(request, gatewayUrl) {
105
+ const fetchOptions = {
106
+ method: 'POST',
107
+ headers: {
108
+ 'Content-Type': 'application/json',
109
+ },
110
+ body: JSON.stringify(request),
111
+ };
112
+ const response = await fetch(`${gatewayUrl}/reencrypt`, fetchOptions);
113
+ if (!response.ok) {
114
+ throw new Error(`Reencrypt failed: gateway respond with HTTP code ${response.status}: ${JSON.stringify(await response.json())}`);
115
+ }
116
+ const json = await response.json();
117
+ const reencryptResponse = parse(ZamaGatewayReencryptResponse, json);
118
+ if (reencryptResponse.status === 'failure') {
119
+ throw new Error('Reencrypt failed: gateway responded with failure');
120
+ }
121
+ return reencryptResponse;
122
+ }
123
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVlbmNyeXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZoZXZtL3JlZW5jcnlwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2hDLE9BQU8sRUFDTCxnQkFBZ0IsRUFDaEIsZ0JBQWdCLEVBQ2hCLHFCQUFxQixFQUNyQixxQkFBcUIsRUFDckIsVUFBVSxFQUNWLGlDQUFpQyxFQUNqQyxxQkFBcUIsRUFDckIscUJBQXFCLEdBQ3RCLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBMkIsVUFBVSxFQUFFLFdBQVcsRUFBMkIsTUFBTSxNQUFNLENBQUM7QUFDakcsT0FBTyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEQsT0FBTyxFQUNMLGlCQUFpQixFQUVqQixpQkFBaUIsR0FHbEIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTFDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXRELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFpQ2xDLHNEQUFzRDtBQUN0RCxNQUFNLHFCQUFxQixHQUFHO0lBQzVCLElBQUksRUFBRSxxQkFBcUI7SUFDM0IsT0FBTyxFQUFFLEdBQUc7SUFDWixJQUFJLEVBQUUsU0FBUztDQUNoQixDQUFDO0FBRUYsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsRUFDcEMsT0FBTyxFQUNQLFVBQVUsRUFDVixZQUFZLEVBQ1osNkJBQTZCLEVBQzdCLGVBQWUsRUFDZixVQUFVLEVBQ1YsV0FBVyxHQUNTO0lBQ3BCLE1BQU0sZ0JBQWdCLEdBQUcsaUNBQWlDLEVBQUUsQ0FBQztJQUU3RCx3RUFBd0U7SUFDeEUsNkNBQTZDO0lBQzdDLE1BQU0sYUFBYSxHQUFHLG1CQUFtQixD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
@@ -0,0 +1,324 @@
1
+ import { Decoder, RustType } from 'bincode-ts';
2
+ import { Schema } from 'effect';
3
+ import { CompactCiphertextList, CompactPkePublicParams, FheBool, FheTypes, FheUint256, FheUint64, ProvenCompactCiphertextList, set_server_key, TfheClientKey, TfheCompactPublicKey, TfheServerKey, ZkComputeLoad, } from 'node-tfhe';
4
+ import { isAddress } from 'viem';
5
+ import { asBytes32, bytesFromHexString, bytesToBigInt, bytesToHex } from '../binary';
6
+ import { encryptionSchemes, getEncryptionSchemeName, } from '../encryption/encryption';
7
+ import { computeHandle, computePrehandle, HANDLE_VERSION, handleTypes } from '../handle';
8
+ import { parse } from '../schema';
9
+ import { getHandleTypeFromFheType } from './types';
10
+ // This code pulled and modifier from fhevmjs which currently is a relatively poor dependency to extend since it does
11
+ // not expose types correctly and does not export various modules
12
+ // Handed down on a stone tablet from: https://github.com/zama-ai/fhevm-backend/blob/5a70c19a90671cfa4901413db9e162a65c4cf17a/fhevm-engine/fhevm-engine-common/src/utils.rs#L6-L7
13
+ // We use fhevm-backend in KMS and compute services
14
+ export const SERIALIZED_SIZE_LIMIT_CIPHERTEXT = BigInt(1024 * 1024 * 512);
15
+ export const SERIALIZED_SIZE_LIMIT_PK = BigInt(1024 * 1024 * 512);
16
+ export const SERIALIZED_SIZE_LIMIT_CRS = BigInt(1024 * 1024 * 512);
17
+ export const ENCRYPTION_TYPES = {
18
+ 1: 0, // ebool takes 2 encrypted bits
19
+ 4: 1,
20
+ 8: 2,
21
+ 16: 3,
22
+ 32: 4,
23
+ 64: 5,
24
+ 128: 6,
25
+ 160: 7,
26
+ 256: 8,
27
+ 512: 9,
28
+ 1024: 10,
29
+ 2048: 11,
30
+ };
31
+ export function getTfheEncryptor(args) {
32
+ const publicKey = TfheCompactPublicKey.safe_deserialize(args.publicKey, SERIALIZED_SIZE_LIMIT_PK);
33
+ const publicParams = CompactPkePublicParams.safe_deserialize(args.crs2048, SERIALIZED_SIZE_LIMIT_CRS);
34
+ return async ({ context, plaintext, }) => {
35
+ if (plaintext.scheme !== encryptionSchemes.tfhe) {
36
+ throw new Error(`Plaintext with scheme ${getEncryptionSchemeName(plaintext.scheme)} cannot be encrypted with TFHE`);
37
+ }
38
+ const { aclAddress, userAddress, contractAddress, hostChainId } = context;
39
+ const input = createEncryptedInput(aclAddress, hostChainId, publicKey, { 2048: { publicParams } })(userAddress, contractAddress);
40
+ const encInput = await addPlaintextInput(input, plaintext).encrypt();
41
+ // FIXME: support multi-valued ciphertext properly
42
+ const prehandle = encInput.prehandles[0];
43
+ const handle = computeHandle({ prehandle, context });
44
+ return {
45
+ context,
46
+ // The '0x' prefix is required for bytes32 for correct json parsing in foundry, but avoided in ciphertext to avoid bytes-based encoding
47
+ // we may need
48
+ prehandle: asBytes32(prehandle),
49
+ handle: asBytes32(handle),
50
+ ciphertext: {
51
+ scheme: plaintext.scheme,
52
+ type: plaintext.type,
53
+ value: bytesToHex(encInput.ciphertext),
54
+ },
55
+ };
56
+ };
57
+ }
58
+ export function createEncryptedInput(aclContractAddress, chainId, tfheCompactPublicKey, publicParams) {
59
+ return (userAddress, contractAddress) => {
60
+ if (!isAddress(contractAddress)) {
61
+ throw new Error('Contract address is not a valid address.');
62
+ }
63
+ if (!isAddress(userAddress)) {
64
+ throw new Error('User address is not a valid address.');
65
+ }
66
+ const bits = [];
67
+ const builder = CompactCiphertextList.builder(tfheCompactPublicKey);
68
+ const checkLimit = (added) => {
69
+ if (bits.reduce((acc, val) => acc + Math.max(2, val), 0) + added > 2048) {
70
+ throw Error('Packing more than 2048 bits in a single input ciphertext is unsupported');
71
+ }
72
+ if (bits.length + 1 > 256)
73
+ throw Error('Packing more than 256 variables in a single input ciphertext is unsupported');
74
+ };
75
+ function checkEncryptedValue(value, bits) {
76
+ if (value == null)
77
+ throw new Error('Missing value');
78
+ let limit;
79
+ if (bits >= 8) {
80
+ limit = BigInt(`0x${new Array(bits / 8).fill(null).reduce((v) => `${v}ff`, '')}`);
81
+ }
82
+ else {
83
+ limit = BigInt(2 ** bits - 1);
84
+ }
85
+ if (value > limit) {
86
+ throw new Error(`The value exceeds the limit for ${bits}bits integer (${limit.toString()}).`);
87
+ }
88
+ }
89
+ return {
90
+ addBool(value) {
91
+ if (typeof value !== 'bigint' && Number(value) > 1)
92
+ throw new Error('The value must be 1 or 0.');
93
+ checkEncryptedValue(Number(value), 1);
94
+ checkLimit(2);
95
+ builder.push_boolean(!!value);
96
+ bits.push(1); // ebool takes 2 encrypted bits
97
+ return this;
98
+ },
99
+ add4(value) {
100
+ checkEncryptedValue(value, 4);
101
+ checkLimit(4);
102
+ builder.push_u4(Number(value));
103
+ bits.push(4);
104
+ return this;
105
+ },
106
+ add8(value) {
107
+ checkEncryptedValue(value, 8);
108
+ checkLimit(8);
109
+ builder.push_u8(Number(value));
110
+ bits.push(8);
111
+ return this;
112
+ },
113
+ add16(value) {
114
+ checkEncryptedValue(value, 16);
115
+ checkLimit(16);
116
+ builder.push_u16(Number(value));
117
+ bits.push(16);
118
+ return this;
119
+ },
120
+ add32(value) {
121
+ checkEncryptedValue(value, 32);
122
+ checkLimit(32);
123
+ builder.push_u32(Number(value));
124
+ bits.push(32);
125
+ return this;
126
+ },
127
+ add64(value) {
128
+ checkEncryptedValue(value, 64);
129
+ checkLimit(64);
130
+ builder.push_u64(BigInt(value));
131
+ bits.push(64);
132
+ return this;
133
+ },
134
+ add128(value) {
135
+ checkEncryptedValue(value, 128);
136
+ checkLimit(128);
137
+ builder.push_u128(BigInt(value));
138
+ bits.push(128);
139
+ return this;
140
+ },
141
+ addAddress(value) {
142
+ if (!isAddress(value)) {
143
+ throw new Error('The value must be a valid address.');
144
+ }
145
+ checkLimit(160);
146
+ builder.push_u160(BigInt(value));
147
+ bits.push(160);
148
+ return this;
149
+ },
150
+ add256(value) {
151
+ checkEncryptedValue(value, 256);
152
+ checkLimit(256);
153
+ builder.push_u256(BigInt(value));
154
+ bits.push(256);
155
+ return this;
156
+ },
157
+ addBytes64(value) {
158
+ if (value.length !== 64)
159
+ throw Error('Incorrect length of input Uint8Array, should be 64 for an ebytes64');
160
+ const bigIntValue = bytesToBigInt(value);
161
+ checkEncryptedValue(bigIntValue, 512);
162
+ checkLimit(512);
163
+ builder.push_u512(bigIntValue);
164
+ bits.push(512);
165
+ return this;
166
+ },
167
+ addBytes128(value) {
168
+ if (value.length !== 128)
169
+ throw Error('Incorrect length of input Uint8Array, should be 128 for an ebytes128');
170
+ const bigIntValue = bytesToBigInt(value);
171
+ checkEncryptedValue(bigIntValue, 1024);
172
+ checkLimit(1024);
173
+ builder.push_u1024(bigIntValue);
174
+ bits.push(1024);
175
+ return this;
176
+ },
177
+ addBytes256(value) {
178
+ if (value.length !== 256)
179
+ throw Error('Incorrect length of input Uint8Array, should be 256 for an ebytes256');
180
+ const bigIntValue = bytesToBigInt(value);
181
+ checkEncryptedValue(bigIntValue, 2048);
182
+ checkLimit(2048);
183
+ builder.push_u2048(bigIntValue);
184
+ bits.push(2048);
185
+ return this;
186
+ },
187
+ getBits() {
188
+ return bits;
189
+ },
190
+ async encrypt() {
191
+ const getKeys = (obj) => Object.keys(obj);
192
+ const totalBits = bits.reduce((total, v) => total + v, 0);
193
+ const now = Date.now();
194
+ // const ppTypes = getKeys(publicParams);
195
+ const ppTypes = getKeys(publicParams);
196
+ const closestPP = ppTypes.find((k) => Number(k) >= totalBits);
197
+ if (!closestPP) {
198
+ throw new Error(`Too many bits in provided values. Maximum is ${ppTypes[ppTypes.length - 1]}.`);
199
+ }
200
+ const pp = publicParams[closestPP].publicParams;
201
+ const buffContract = bytesFromHexString(contractAddress);
202
+ const buffUser = bytesFromHexString(userAddress);
203
+ const buffAcl = bytesFromHexString(aclContractAddress);
204
+ const buffChainId = bytesFromHexString(chainId.toString(16));
205
+ const auxData = new Uint8Array(buffContract.length + buffUser.length + buffAcl.length + 32);
206
+ auxData.set(buffContract, 0);
207
+ auxData.set(buffUser, 20);
208
+ auxData.set(buffAcl, 40);
209
+ auxData.set(buffChainId, auxData.length - buffChainId.length);
210
+ const encrypted = builder.build_with_proof_packed(pp, auxData, ZkComputeLoad.Proof);
211
+ const ciphertext = Buffer.from(encrypted.safe_serialize(SERIALIZED_SIZE_LIMIT_CIPHERTEXT));
212
+ // These prehandles have the expected layout expected by verifyCiphertext
213
+ // including type and version metadata
214
+ const prehandles = [];
215
+ for (let i = 0; i < encrypted.len(); i++) {
216
+ const handleType = getHandleTypeFromFheType(encrypted.get_kind_of(i));
217
+ prehandles[i] = computePrehandle({
218
+ ciphertext,
219
+ handleType: handleType,
220
+ handleVersion: HANDLE_VERSION,
221
+ indexHandle: i,
222
+ });
223
+ }
224
+ return {
225
+ prehandles,
226
+ ciphertext,
227
+ };
228
+ },
229
+ };
230
+ };
231
+ }
232
+ export function addPlaintextInput(input, plaintext) {
233
+ switch (plaintext.type) {
234
+ case handleTypes.ebool:
235
+ return input.addBool(plaintext.value);
236
+ case handleTypes.euint64:
237
+ return input.add64(plaintext.value);
238
+ case handleTypes.euint256:
239
+ return input.add256(plaintext.value);
240
+ }
241
+ }
242
+ // Decryption...
243
+ export function getTfheDecryptor({ cks }) {
244
+ const clientKey = TfheClientKey.safe_deserialize(cks, SERIALIZED_SIZE_LIMIT_CIPHERTEXT);
245
+ const serverKey = TfheServerKey.new(clientKey);
246
+ set_server_key(serverKey);
247
+ return async ({ scheme, type, value, }) => {
248
+ if (scheme !== encryptionSchemes.tfhe) {
249
+ throw new Error(`Ciphertext with scheme ${getEncryptionSchemeName(scheme)} cannot be decrypted with TFHE`);
250
+ }
251
+ const handleType = type;
252
+ const ctBuf = bytesFromHexString(value);
253
+ const header = decodeTfheSerializationHeader(ctBuf);
254
+ // For now just support a singleton ciphertext list
255
+ if (header.name === ProvenCompactCiphertextListTypeName) {
256
+ const encrypted = ProvenCompactCiphertextList.safe_deserialize(ctBuf, SERIALIZED_SIZE_LIMIT_CIPHERTEXT);
257
+ const decrypted = encrypted.expand_without_verification();
258
+ const kind = decrypted.get_kind_of(0);
259
+ return fromCiphertextList(decrypted, clientKey);
260
+ }
261
+ const decryptor = decryptionClasses[handleType];
262
+ if (!decryptor) {
263
+ throw new Error(`Unsupported handle type: ${handleType}`);
264
+ }
265
+ const encrypted = decryptor.safe_deserialize(ctBuf, SERIALIZED_SIZE_LIMIT_CIPHERTEXT);
266
+ const decrypted = encrypted.decrypt(clientKey);
267
+ // First assign to unnarrowed plaintext to avoid concealing type
268
+ const plaintext = { scheme: encryptionSchemes.tfhe, type: handleType, value: decrypted };
269
+ return plaintext;
270
+ };
271
+ }
272
+ function fromCiphertextList(decrypted, clientKey) {
273
+ const kind = decrypted.get_kind_of(0);
274
+ const scheme = encryptionSchemes.tfhe;
275
+ switch (kind) {
276
+ case FheTypes.Bool:
277
+ return { scheme, type: handleTypes.ebool, value: decrypted.get_bool(0).decrypt(clientKey) };
278
+ case FheTypes.Uint64:
279
+ return { scheme, type: handleTypes.euint64, value: decrypted.get_uint64(0).decrypt(clientKey) };
280
+ case FheTypes.Uint256:
281
+ return { scheme, type: handleTypes.euint256, value: decrypted.get_uint256(0).decrypt(clientKey) };
282
+ }
283
+ throw new Error(`Unsupported kind: ${kind}`);
284
+ }
285
+ const decryptionClasses = {
286
+ [handleTypes.ebool]: FheBool,
287
+ [handleTypes.euint64]: FheUint64,
288
+ [handleTypes.euint256]: FheUint256,
289
+ };
290
+ var VersioningMode;
291
+ (function (VersioningMode) {
292
+ VersioningMode[VersioningMode["Versioned"] = 0] = "Versioned";
293
+ VersioningMode[VersioningMode["Unversioned"] = 1] = "Unversioned";
294
+ })(VersioningMode || (VersioningMode = {}));
295
+ // Representation of (https://github.com/zama-ai/tfhe-rs/blob/8ee1bdd9a935e9f00c72238f2ff5220ccf77c850/tfhe/src/safe_serialization.rs#L75-L79):
296
+ // struct SerializationHeader {
297
+ // header_version: Cow<'static, str>,
298
+ // versioning_mode: SerializationVersioningMode,
299
+ // name: Cow<'static, str>,
300
+ // }
301
+ export const SerializationHeader = RustType.Struct([
302
+ ['header_version', RustType.Str],
303
+ [
304
+ 'versioning_mode',
305
+ RustType.Enum({ [VersioningMode.Versioned]: RustType.Str, [VersioningMode.Unversioned]: RustType.Str }),
306
+ ],
307
+ ['name', RustType.Str],
308
+ ]);
309
+ // Output schema (note we currently strip the versioning_mode field because we do not care about it, only the name
310
+ export const ProvenCompactCiphertextListTypeName = 'high_level_api::ProvenCompactCiphertextList';
311
+ export const FheUintTypeName = 'high_level_api::FheUint';
312
+ export const TfheSerialisationTypeName = Schema.Literal(ProvenCompactCiphertextListTypeName, FheUintTypeName);
313
+ export const TfheSerializationHeader = Schema.Struct({
314
+ header_version: Schema.String,
315
+ // For now, we will accept any string to avoid having to define an exhaustive union above
316
+ name: Schema.Union(TfheSerialisationTypeName, Schema.String),
317
+ });
318
+ // Decode a serialisation header from a ciphertext or other bincode-serialised data from tfhe-rs
319
+ export function decodeTfheSerializationHeader(buffer) {
320
+ const decoder = new Decoder();
321
+ const decoded = decoder.load(Uint8Array.from(buffer).buffer).decodeAs(SerializationHeader);
322
+ return parse(TfheSerializationHeader, decoded);
323
+ }
324
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGZoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9maGV2bS90ZmhlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQy9DLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDaEMsT0FBTyxFQUNMLHFCQUFxQixFQUVyQixzQkFBc0IsRUFDdEIsT0FBTyxFQUNQLFFBQVEsRUFDUixVQUFVLEVBQ1YsU0FBUyxFQUNULDJCQUEyQixFQUMzQixjQUFjLEVBQ2QsYUFBYSxFQUNiLG9CQUFvQixFQUNwQixhQUFhLEVBQ2IsYUFBYSxHQUNkLE1BQU0sV0FBVyxDQUFDO0FBQ25CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDakMsT0FBTyxFQUFFLFNBQVMsRUFBRSxrQkFBa0IsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3JGLE9BQU8sRUFHTCxpQkFBaUIsRUFHakIsdUJBQXVCLEdBTXhCLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sU0FBUyxDQUFDO0FBRW5ELHFIQUFxSDtBQUNySCxtRUFBbUU7QUFFbkUsaUxBQWlMO0FBQ2pMLG1EQUFtRDtBQUNuRCxNQUFNLENBQUMsTUFBTSxnQ0FBZ0MsR0FBRyxNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztBQUMxRSxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztB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