Writing an FHE program
An FHE program is simply a Rust function with an annotation and a few restrictions. However, unlike standard Rust functions, FHE programs work with encrypted data!
The #[fhe_program(...)]
attribute
To indicate that a function is an FHE program, simply add the #[fhe_program()]
attribute to an fn
function:
#![allow(unused)] fn main() { use sunscreen::{ fhe_program, }; #[fhe_program(scheme = "bfv")] fn my_fhe_program() { } }
This attribute takes a single scheme
argument. Currently, this argument value should always be "bfv"
, our supported FHE scheme.
FHE program interface requirements
FHE programs implement their logic in the fn
function beneath the #[fhe_program()]
attribute. The function you write must satisfy some conditions:
- Your
fn
function must be non-generic and stand-alone (i.e. not astruct
method, closure,trait
method, etc). - Your
fn
function may take any number of arguments. - Each argument must be of either type
T
(i.e. plaintext) orCipher<T>
(i.e. ciphertext), whereT
is a type supported in FHE programs. Every argument need not be the sameT
. - Your
fn
function must return either aCipher<T>
or a tuple of(Cipher<T1>, Cipher<T2>, ...)
values (i.e. return values are always encrypted). As with arguments, types must be supported in FHE programs.
Here's an example of an FHE program that returns a tuple containing two encrypted values: a * b
and a + c
.
#![allow(unused)] fn main() { use sunscreen::{ fhe_program, types::{bfv::Signed, Cipher}, }; #[fhe_program(scheme = "bfv")] fn multiple_returns(a: Cipher<Signed>, b: Cipher<Signed>, c: Signed) -> (Cipher<Signed>, Cipher<Signed>) { (a * b, a + c) } }
Operations
In FHE programs, you can:
- Perform basic operations (
+
,-
,*
,/
,<<
,>>
). The supported set of operations vary from type to type. Note that at least one of the operands must be a ciphertext. - Call functions.
- Use any Rust construct (e.g.
match
,for i in ...
,if...else
) on data not derived from any argument. We walk through a number of examples in the limitations chapter.