Smart contracts - fhEVM API
This document provides an overview of the functions available in the TFHE
Solidity library. The TFHE library provides functionality for working with encrypted types and performing operations on them. It implements fully homomorphic encryption (FHE) operations in Solidity.
Overview
The TFHE
Solidity library provides essential functionality for working with encrypted data types and performing fully homomorphic encryption (FHE) operations in smart contracts. It is designed to streamline the developer experience while maintaining flexibility and performance.
Core Functionality
Homomorphic Operations: Enables arithmetic, bitwise, and comparison operations on encrypted values.
Ciphertext-Plaintext Interoperability: Supports operations that mix encrypted and plaintext operands, provided the plaintext operand's size does not exceed the encrypted operand's size.
Example:
add(uint8 a, euint8 b)
is valid, butadd(uint32 a, euint16 b)
is not.Ciphertext-plaintext operations are generally faster and consume less gas than ciphertext-ciphertext operations.
Implicit Upcasting: Automatically adjusts operand types when necessary to ensure compatibility during operations on encrypted data.
Key Features
Flexibility: Handles a wide range of encrypted data types, including booleans, integers, addresses, and byte arrays.
Performance Optimization: Prioritizes efficient computation by supporting optimized operator versions for mixed plaintext and ciphertext inputs.
Ease of Use: Offers consistent APIs across all supported data types, enabling a smooth developer experience.
The library ensures that all operations on encrypted data follow the constraints of FHE while abstracting complexity, allowing developers to focus on building privacy-preserving smart contracts.
Types
Encrypted Data Types
Boolean
ebool
: Encrypted boolean value
Unsigned Integers
euint4
: Encrypted 4-bit unsigned integereuint8
: Encrypted 8-bit unsigned integereuint16
: Encrypted 16-bit unsigned integereuint32
: Encrypted 32-bit unsigned integereuint64
: Encrypted 64-bit unsigned integereuint128
: Encrypted 128-bit unsigned integereuint256
: Encrypted 256-bit unsigned integer
Addresses & Bytes
eaddress
: Encrypted Ethereum addressebytes64
: Encrypted 64-byte valueebytes128
: Encrypted 128-byte valueebytes256
: Encrypted 256-byte value
Special Types
einput
: Input type for encrypted operations (bytes32)
Casting Types
Casting between encrypted types:
TFHE.asEbool
converts encrypted integers to encrypted booleansCasting to encrypted types:
TFHE.asEuintX
converts plaintext values to encrypted typesCasting to encrypted addresses:
TFHE.asEaddress
converts plaintext addresses to encrypted addressesCasting to encrypted bytes:
TFHE.asEbytesX
converts plaintext bytes to encrypted bytes
asEuint
asEuint
The asEuint
functions serve three purposes:
verify ciphertext bytes and return a valid handle to the calling smart contract;
cast a
euintX
typed ciphertext to aeuintY
typed ciphertext, whereX != Y
;trivially encrypt a plaintext value.
The first case is used to process encrypted inputs, e.g. user-provided ciphertexts. Those are generally included in a transaction payload.
The second case is self-explanatory. When X > Y
, the most significant bits are dropped. When X < Y
, the ciphertext is padded to the left with trivial encryptions of 0
.
The third case is used to "encrypt" a public value so that it can be used as a ciphertext. Note that what we call a trivial encryption is not secure in any sense. When trivially encrypting a plaintext value, this value is still visible in the ciphertext bytes. More information about trivial encryption can be found here.
Examples
asEbool
asEbool
The asEbool
functions behave similarly to the asEuint
functions, but for encrypted boolean values.
Core Functions
Configuration
Sets the FHEVM configuration for encrypted operations.
Initialization Checks
Returns true if the encrypted value is initialized, false otherwise. Supported for all encrypted types (T can be ebool, euintX, eaddress, ebytesX).
Arithmetic operations
Available for euint* types:
Arithmetic:
TFHE.add
,TFHE.sub
,TFHE.mul
,TFHE.min
,TFHE.max
,TFHE.neg
,TFHE.div
,TFHE.rem
Note:
div
andrem
operations are supported only with plaintext divisors
Arithmetic operations (add
, sub
, mul
, div
, rem
)
add
, sub
, mul
, div
, rem
)Performs the operation homomorphically.
Note that division/remainder only support plaintext divisors.
Examples
Min/Max Operations - min
, max
min
, max
Available for euint* types:
Returns the minimum (resp. maximum) of the two given values.
Examples
Unary operators (neg
, not
)
neg
, not
)There are two unary operators: neg
(-
) and not
(!
). Note that since we work with unsigned integers, the result of negation is interpreted as the modular opposite. The not
operator returns the value obtained after flipping all the bits of the operand.
More information about the behavior of these operators can be found at the TFHE-rs docs.
Bitwise operations
Bitwise:
TFHE.and
,TFHE.or
,TFHE.xor
,TFHE.not
,TFHE.shl
,TFHE.shr
,TFHE.rotl
,TFHE.rotr
Bitwise operations (AND
, OR
, XOR
)
AND
, OR
, XOR
)Unlike other binary operations, bitwise operations do not natively accept a mix of ciphertext and plaintext inputs. To ease developer experience, the TFHE
library adds function overloads for these operations. Such overloads implicitely do a trivial encryption before actually calling the operation function, as shown in the examples below.
Available for euint* types:
Examples
Bit shift operations (<<
, >>
)
<<
, >>
)Shifts the bits of the base two representation of a
by b
positions.
Examples
Rotate operations
Rotates the bits of the base two representation of a
by b
positions.
Examples
Comparison operation (eq
, ne
, ge
, gt
, le
, lt
)
eq
, ne
, ge
, gt
, le
, lt
)Note that in the case of ciphertext-plaintext operations, since our backend only accepts plaintext right operands, calling the operation with a plaintext left operand will actually invert the operand order and call the opposite comparison.
The result of comparison operations is an encrypted boolean (ebool
). In the backend, the boolean is represented by an encrypted unsinged integer of bit width 8, but this is abstracted away by the Solidity library.
Available for all encrypted types:
Additional comparisons for euint* types:
Examples
Multiplexer operator (select
)
select
)If control is true, returns a, otherwise returns b. Available for ebool, eaddress, and ebytes* types.
This operator takes three inputs. The first input b
is of type ebool
and the two others of type euintX
. If b
is an encryption of true
, the first integer parameter is returned. Otherwise, the second integer parameter is returned.
Example
Generating random encrypted integers
Random encrypted integers can be generated fully on-chain.
That can only be done during transactions and not on an eth_call
RPC method, because PRNG state needs to be mutated on-chain during generation.
Example
Access control functions
The TFHE
library provides a robust set of access control functions for managing permissions on encrypted values. These functions ensure that encrypted data can only be accessed or manipulated by authorized accounts or contracts.
Permission management
Functions
Descriptions
allow
: Grants permanent access to a specific address. Permissions are stored persistently in a dedicated ACL contract.allowThis
: Grants the current contract access to an encrypted value.allowTransient
: Grants temporary access to a specific address for the duration of the transaction. Permissions are stored in transient storage for reduced gas costs.
Access control list (ACL) overview
The allow
and allowTransient
functions enable fine-grained control over who can access, decrypt, and reencrypt encrypted values. Temporary permissions (allowTransient
) are ideal for minimizing gas usage in scenarios where access is needed only within a single transaction.
Example: granting access
Permission checks
Functions
Descriptions
isAllowed
: Checks whether a specific address has permission to access a ciphertext.isSenderAllowed
: Similar toisAllowed
, but automatically checks permissions for themsg.sender
.
Both functions return true
if the ciphertext is authorized for the specified address, regardless of whether the allowance is stored in the ACL contract or in transient storage.
Verifying Permissions
These functions help ensure that only authorized accounts or contracts can access encrypted values.
Example: permission verification
Storage Management
Function
Description
cleanTransientStorage
: Removes all temporary permissions from transient storage. Use this function at the end of a transaction to ensure no residual permissions remain.
Example
Additional Notes
Underlying implementation: All encrypted operations and access control functionalities are performed through the underlying
Impl
library.Uninitialized values: Uninitialized encrypted values are treated as
0
(for integers) orfalse
(for booleans) in computations.Implicit casting: Type conversion between encrypted integers of different bit widths is supported through implicit casting, allowing seamless operations without additional developer intervention.
Last updated