FheLib is a library implemented inside fhevm-go. It offers FHE-related functionalities such as homomorphic operations, decryption/reencryption requests and so on. FheLib is exposed as a single precompiled contract (or a precompile for short) that is integrated into the underlying blockchain.
FheLib functions can be called by calling the FheLib precompile with a respective EVM function selector.
This page describes the required inputs, behaviours and outputs of some of these functions.
GetCiphertext Function (selector: e4b808cb)
The GetCiphertext function returns a serialized TFHE ciphertext from protected storage given:
contract address where the ciphertext is stored at
the ebool/e(u)int value (also called a handle) for which the ciphertext is requested
GetCiphertext only works via the eth_call RPC.
To call GetCiphertext via eth_call, the following Python can serve as an example:
import http.client
import json
# This is the address of the FheLib precompile. This value is hardcoded per blockchain.
fhe_lib_precompile_address = "0x000000000000000000000000000000000000005d"
# The contract address where the ciphertext is stored at.
contract_address = "ACD7Be4EBF68Bf2A5b6eB0CaFb15460C169BC459"
# 12 bytes of 0s for padding the contract address.
address_zero_padding = "000000000000000000000000"
# The ebool/e(u)int value for which the ciphertext is requested.
handle = "f038cdc8bf630e239f143abeb039b91ec82ec17a8460582e7a409fa551030c06"
# The function selector of GetCiphertext.
get_ciphertext_selector = "e4b808cb"
# Call the FheLib precompile with `data` being the concatenation of:
# - getCiphertext function selector;
# - 12 bytes of 0s to padd the contract address;
# - contract address;
# - the handle to the ciphertext.
payload = {
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": fhe_lib_precompile_address,
"data": "0x" + get_ciphertext_selector + address_zero_padding +
contract_address + handle
},
"latest"
],
"id": 1,
}
con = http.client.HTTPConnection("localhost", 8545)
con.request("POST", "/", body=json.dumps(payload),
headers={"Content-Type": "application/json"})
resp = json.loads(con.getresponse().read())
# Remove leading "0x" and decode hex to get a byte buffer with the ciphertext.
ciphertext = bytes.fromhex(resp["result"][2:])
fhevm-go is an open-source library used to easily integrate the fhEVM into an EVM-compatible blockchain.
Main features
fhevm-go gives your EVM the ability to compute on encrypted data using fully homomorphic encryption by:
a collection of operations on encrypted data via precompiled contracts
various additional EVM components that support encrypted computation
Target users
The library helps EVM maintainers to extend their EVM with the power of FHE. If you are looking for a library to deploy and use smart contracts on an fhEVM, you should better look at fhevm
License
This software is distributed under the BSD-3-Clause-Clear license. If you have any questions, please contact us at hello@zama.ai.
Initial Setup
In order to use the library, you need to clone the repository and build it. This is required because the library depends on the tfhe-rs library that needs to be built from source (for now), and Go doesn't support such a build.
$ git clone https://github.com/zama-ai/fhevm-go
$ cd fhevm-go
$ make build
You can now use it in your project by adding it to go.mod, and adding a replace to point to your local build. An example using fhevm-go v1.0.0:
The replace is necessary for now as Go build system can't build the tfhe-rs library that fhevm-go needs. It's therefore necessary that we build it manually as mentioned above, then point to our ready-to-use directory in go.mod
Integration
This document is a guide listing detailed steps to integrate fhevm-go into go-ethereum or any other implementations that follow the same architecture.
After initializing evm.interpreter make sure to point fhevmEnvironment to it evm.fhevmEnvironment.interpreter = evm.interpreter then initialize it fhevm.InitFhevm(&evm.fhevmEnvironment)
Update RunPrecompiledContract
After changing precompiled contract interface in 2, we have to change usages of:
In opCall, opCallCode and opStaticCall, add lines to delegate ciphertexts before the call and to restore at the end of function (using defer)
There might be other functions that calls other contracts (e.g. opDelegateCall), in which case you will also need to do the same modifications as below. Basically, anything that will execute code after incrementing the depth would need this.