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
fnfunction must be non-generic and stand-alone (i.e. not astructmethod, closure,traitmethod, etc). - Your
fnfunction may take any number of arguments. - Each argument must be of either type
T(i.e. plaintext) orCipher<T>(i.e. ciphertext), whereTis a type supported in FHE programs. Every argument need not be the sameT. - Your
fnfunction 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.