The TFHE
library defines the following operations with FHE ciphertexts:
NOTE: The shift operators
TFHE.shr
andTFHE.shl
can take any encrypted typeeuintX
as a first operand and either auint8
or aeuint8
as a second operand, however the second operand will always be computed modulo the number of bits of the first operand. For example,TFHE.shr(euint64 x, 70)
will actually be equal toTFHE.shr(euint64 x, 6)
because70 % 64 = 6
. This is in contrast to the classical shift operators in Solidity where there is no intermediate modulo operation, so for instance anyuint64
shifted right via>>
would give a null result.
Overloaded operators +
, -
, *
, &
, ... on encrypted integers are supported (using for). As of now, overloaded operators will call the versions without an overflow check.
More information about the supported operations can be found in the function specifications page or in the TFHE-rs docs.
If you find yourself in search of a missing feature, we encourage you to consult our roadmap for upcoming developments. Alternatively, don't hesitate to reach out to us on Discord or visit our community forum.
Zama 5-Question Developer Survey
We want to hear from you! Take 1 minute to share your thoughts and helping us enhance our documentation and libraries. 👉 Click here to participate.
The TFHE
library provides encrypted integer types and a type system that is checked both at compile time and at run time.
Encrypted integers with overflow checking are coming soon to the TFHE
library. They will allow reversal in case of an overflow, but will leak some information about the operands.
In terms of implementation in the fhEVM
, encrypted integers take the form of FHE ciphertexts. The TFHE
library abstracts away that and, instead, exposes ciphertext handles to smart contract developers. The e(u)int
types are wrappers over these handles.
The following encrypted data types are defined:
Higher-precision integers are supported in the TFHE-rs
library and can be added as needed to fhEVM
.
You can cast types with asEuint
/asEbool
methods.
If you require a state variable that utilizes these encrypted types, you cannot assign the value with immutable
or constant
keyword. If you're using these types, the compiler attempts to ascertain the value of TFHE.asEuintXX(yy)
during compilation, which is not feasible because asEuintXX()
invokes a precompiled contract. To address this challenge, you must not declare your encrypted state variables as immutable
or constant
. Still, you can use the following methods to set your variables:
name | function name | symbol | type |
---|---|---|---|
Encrypted integers behave as much as possible as Solidity's integer types. Currently, however, behaviour such as "revert on overflow" is not supported as this would leak some information about the encrypted value. Therefore, arithmetic on e(u)int
types is , i.e. there is wrap-around on overflow.
type | supported |
---|
Add
TFHE.add
+
Binary
Sub
TFHE.sub
-
Binary
Mul
TFHE.mul
*
Binary
Div (plaintext divisor)
TFHE.div
Binary
Rem (plaintext divisor)
TFHE.rem
Binary
BitAnd
TFHE.and
&
Binary
BitOr
TFHE.or
|
Binary
BitXor
TFHE.xor
^
Binary
Shift Right
TFHE.shr
Binary
Shift Left
TFHE.shl
Binary
Rotate Right
TFHE.rotr
Binary
Rotate Left
TFHE.rotl
Binary
Equal
TFHE.eq
Binary
Not equal
TFHE.ne
Binary
Greater than or equal
TFHE.ge
Binary
Greater than
TFHE.gt
Binary
Less than or equal
TFHE.le
Binary
Less than
TFHE.lt
Binary
Min
TFHE.min
Binary
Max
TFHE.max
Binary
Neg
TFHE.neg
-
Unary
Not
TFHE.not
~
Unary
Select
TFHE.select
Ternary
Random unsigned int
TFHE.randEuintX()
Random
| yes |
| yes |
| yes |
| yes |
| yes |
| yes |
| no, coming soon |
| no, coming soon |
| yes |
| no, coming soon |
| no, coming soon |
| yes |
| no, coming soon |
| no, coming soon |
| no, coming soon |
| no, coming soon |
| no, coming soon |
| no, coming soon |
The result of comparison operations is of type ebool
. Typical boolean operations are not supported for this type, because it is an encrypted boolean.
fhEVM provides a method which acts as a ternary operator on encrypted integers. This method is called select.
It is important to keep in mind that each time we assign a value using TFHE.select
, the value changes, even if the plaintext value remains the same.
If a condition is not satisfied, the transaction will not be reverted, potentially posing a challenge when attempting to communicate issues to users. A recommended approach to address this is by implementing an error handler in which the contract stores the latest error information for all wallets.