mirror of
https://github.com/zama-ai/fhevm-solidity.git
synced 2026-05-09 03:00:27 -04:00
156 lines
5.7 KiB
Markdown
156 lines
5.7 KiB
Markdown
# fhevmjs function specifications
|
|
|
|
This document provides an overview of the `fhevmjs` library, detailing its initialization, instance creation, input handling, encryption, and re-encryption processes.
|
|
|
|
[fhevmjs](https://github.com/zama-ai/fhevmjs/) is designed to assist in creating encrypted inputs and retrieving re-encryption data off-chain through a gateway. The library works with any fhEVM and fhEVM Coprocessors.
|
|
|
|
## Init (browser)
|
|
|
|
If you are using `fhevmjs` in a web application, you need to initialize it before creating an instance. To do this, you should call `initFhevm` and wait for the promise to resolve.
|
|
|
|
```javascript
|
|
import { initFhevm, createInstance } from "fhevmjs";
|
|
|
|
|
|
initFhevm().then(() => {
|
|
const instance = await createInstance({
|
|
kmsContractAddress: '0x208De73316E44722e16f6dDFF40881A3e4F86104',
|
|
aclContractAddress: '0xc9990FEfE0c27D31D0C2aa36196b085c0c4d456c',
|
|
networkUrl: "https://devnet.zama.ai/",
|
|
gatewayUrl: "https://gateway.zama.ai/",
|
|
});
|
|
});
|
|
```
|
|
|
|
## Create instance
|
|
|
|
This function returns an instance of fhevmjs, which accepts an object containing:
|
|
|
|
- `kmsContractAddress`: the address of the KMSVerifier contract;
|
|
- `aclContractAddress`: the address of the ACL contract;
|
|
- `networkUrl` or `network`: the URL or Eip1193 object provided by `window.ethereum` - used to fetch chainId and KMS nodes' public key
|
|
- `gatewayUrl`: the URL of the gateway - used to retrieve the public key, ZKPoK public parameters and send inputs and get reencryption
|
|
- `chainId` (optional): the chainId of the network
|
|
- `publicKey` (optional): if the public key has been fetched separately or stored in cache, you can provide it
|
|
- `publicParams` (optional): if the public params has been fetched separately or stored in cache, you can provide it
|
|
|
|
```javascript
|
|
import { createInstance } from "fhevmjs";
|
|
|
|
const instance = await createInstance({
|
|
kmsContractAddress: "0x208De73316E44722e16f6dDFF40881A3e4F86104",
|
|
aclContractAddress: "0xc9990FEfE0c27D31D0C2aa36196b085c0c4d456c",
|
|
networkUrl: "https://devnet.zama.ai/",
|
|
gatewayUrl: "https://gateway.zama.ai/",
|
|
});
|
|
```
|
|
|
|
Using `window.ethereum` object:
|
|
|
|
```javascript
|
|
import { createInstance } from "fhevmjs";
|
|
|
|
const instance = await createInstance({
|
|
kmsContractAddress: "0x208De73316E44722e16f6dDFF40881A3e4F86104",
|
|
aclContractAddress: "0xc9990FEfE0c27D31D0C2aa36196b085c0c4d456c",
|
|
network: window.ethereum,
|
|
gatewayUrl: "https://gateway.zama.ai/",
|
|
});
|
|
```
|
|
|
|
## Input
|
|
|
|
This method creates an encrypted input and returns an input object. It requires both the user address and the contract address to ensure the encrypted input isn't reused inappropriately in a different context.
|
|
An input can include **multiple values of various types**, resulting in a single ciphertext that packs these values.
|
|
|
|
```javascript
|
|
const userAddress = "0xa5e1defb98EFe38EBb2D958CEe052410247F4c80";
|
|
const contractAddress = "0xfCefe53c7012a075b8a711df391100d9c431c468";
|
|
|
|
const input = instance.createEncryptedInput(contractAddress, userAddress);
|
|
```
|
|
|
|
### input.addBool, input.add8, ...
|
|
|
|
Input object has different method to add values:
|
|
|
|
- `addBool`
|
|
- `add4`
|
|
- `add8`
|
|
- `add16`
|
|
- `add32`
|
|
- `add64`
|
|
- `add128`
|
|
- `add256`
|
|
- `addBytes64`
|
|
- `addBytes128`
|
|
- `addBytes256`
|
|
- `addAddress`
|
|
|
|
```javascript
|
|
const input = instance.createEncryptedInput(contractAddress, userAddress);
|
|
|
|
input.addBool(true);
|
|
input.add16(239);
|
|
input.addAddress("0xa5e1defb98EFe38EBb2D958CEe052410247F4c80");
|
|
input.addBool(true);
|
|
```
|
|
|
|
### input.encrypt and input.send
|
|
|
|
These methods process values and return the necessary data for use on the blockchain. The `encrypt` method encrypts these values and provides parameters for use. The `send` method encrypts, dispatches the ciphertext and proof to the coprocessor, and returns the required parameters.
|
|
|
|
```javascript
|
|
input.addBool(true);
|
|
input.addBool(true);
|
|
input.add8(4);
|
|
const inputs = await input.encrypt(); // or input.send() if using a coprocessor
|
|
|
|
contract.myExample(
|
|
"0xa5e1defb98EFe38EBb2D958CEe052410247F4c80",
|
|
inputs.handles[0],
|
|
32,
|
|
inputs.handles[1],
|
|
inputs.handles[2],
|
|
true,
|
|
inputs.inputProof,
|
|
);
|
|
```
|
|
|
|
## Reencryption
|
|
|
|
### Keypair
|
|
|
|
A keypair consists of a private key and a public key, both generated by the dApp. These keys are used to reencrypt a blockchain ciphertext, allowing it to be securely transferred to user-specific keypairs.
|
|
|
|
```javascript
|
|
// Generate the private and public key, used for the reencryption
|
|
const { publicKey, privateKey } = instance.generateKeypair();
|
|
```
|
|
|
|
Verifying that the public key used in the reencryption process belongs to the user requires the user to sign the public key linked to a specific contract address. This signature allows any ciphertext allowed for the user and the contract can be reencrypted using the signed public key.
|
|
To streamline user interaction during the signature process, we utilize the EIP712 standard as the object to be signed.
|
|
|
|
```javascript
|
|
// Create an EIP712 object for the user to sign.
|
|
const eip712 = instance.createEIP712(publicKey, CONTRACT_ADDRESS);
|
|
```
|
|
|
|
This `eip712` can be signed using `eth_signTypedData_v4` for example in a browser:
|
|
|
|
```javascript
|
|
const params = [USER_ADDRESS, JSON.stringify(eip712)];
|
|
const signature = await window.ethereum.request({ method: "eth_signTypedData_v4", params });
|
|
```
|
|
|
|
Note: it is recommended to store the keypair and the signature in the user's browser to avoid re-requesting signature on every user connection.
|
|
|
|
### Reencryption
|
|
|
|
Reencrypt method will use the `gatewayUrl` to get the reencryption of a ciphertext and decrypt it.
|
|
|
|
```javascript
|
|
const handle = await erc20.balanceOf(userAddress); // returns the handle of hte ciphertext as a uint256 (bigint)
|
|
const myBalance = await instance.reencrypt(handle, privateKey, publicKey, signature, contractAddress, userAddress);
|
|
```
|