# Tutorial

## Quick Start

The basic steps for using the high-level API of TFHE-rs are:

1. Importing the TFHE-rs prelude;
2. Client-side: Configuring and creating keys;
3. Client-side: Encrypting data;
4. Server-side: Setting the server key;
5. Server-side: Computing over encrypted data;
6. Client-side: Decrypting data.

Here is a full example (combining the client and server parts):

```rust
use tfhe::{ConfigBuilder, generate_keys, set_server_key, FheUint8};
use tfhe::prelude::*;

fn main() {
    let config = ConfigBuilder::all_disabled()
        .enable_default_integers()
        .build();

    // Client-side
    let (client_key, server_key) = generate_keys(config);

    let clear_a = 27u8;
    let clear_b = 128u8;

    let a = FheUint8::encrypt(clear_a, &client_key);
    let b = FheUint8::encrypt(clear_b, &client_key);

    //Server-side
    set_server_key(server_key);
    let result = a + b;

    //Client-side
    let decrypted_result: u8 = result.decrypt(&client_key);

    let clear_result = clear_a + clear_b;

    assert_eq!(decrypted_result, clear_result);
}
```

The default configuration for x86 Unix machines:
```toml
tfhe = { version = "0.3.0", features = ["integer", "x86_64-unix"]}
```

Configuration options for different platforms can be found [here](../getting_started/installation.md). Other rust and homomorphic types features can be found [here](../how_to/rust_configuration.md).

### Imports.

`tfhe` uses `traits` to have a consistent API for creating FHE types and enable users to write generic functions. To be able to use associated functions and methods of a trait, the trait has to be in scope.

To make it easier, the `prelude` 'pattern' is used. All of the important `tfhe` traits are in a `prelude` module that you can **glob import**. With this, there is no need to remember or know the traits that you want to import.

```rust
use tfhe::prelude::*;
```

### 1. Configuring and creating keys.

The first step is the creation of the configuration. The configuration is used to declare which type you will (or will not) use, as well as enabling you to use custom crypto-parameters for these types. Custom parameters should only be used for more advanced usage and/or testing.

A configuration can be created by using the ConfigBuilder type.

In this example, 8-bit unsigned integers with default parameters are used. The `integers` 
feature must also be enabled, as per the table on [this page](../how_to/rust_configuration.md#choosing-your-features).

The config is generated by first creating a builder with all types deactivated. Then, the integer types with default parameters are activated, since we are going to use FheUint8 values.

```rust
use tfhe::{ConfigBuilder, generate_keys};

fn main() {
    let config = ConfigBuilder::all_disabled()
        .enable_default_integers()
        .build();

    let (client_key, server_key) = generate_keys(config);
}
```

The `generate_keys` command returns a client key and a server key.

The `client_key` is meant to stay private and not leave the client, whereas the `server_key` can be made public and sent to a server for it to enable FHE computations.

### 2. Setting the server key.

The next step is to call `set_server_key`

This function will **move** the server key to an internal state of the crate and manage the details to give a simpler interface.

```rust
use tfhe::{ConfigBuilder, generate_keys, set_server_key};

fn main() {
    let config = ConfigBuilder::all_disabled()
        .enable_default_integers()
        .build();

    let (client_key, server_key) = generate_keys(config);

    set_server_key(server_key);
}
```

### 3. Encrypting data.

Encrypting data is achieved via the `encrypt` associated function of the FheEncrypt trait.

Types exposed by this crate implement at least one of FheEncrypt or FheTryEncrypt to allow encryption.

```Rust
let clear_a = 27u8;
let clear_b = 128u8;

let a = FheUint8::encrypt(clear_a, &client_key);
let b = FheUint8::encrypt(clear_b, &client_key);
```

### 4. Computation and decryption.

Computations should be as easy as normal Rust to write, thanks to the usage of operator overloading.

```Rust
let result = a + b;
```

The decryption is achieved by using the `decrypt` method, which comes from the FheDecrypt trait.

```Rust
let decrypted_result: u8 = result.decrypt(&client_key);

let clear_result = clear_a + clear_b;

assert_eq!(decrypted_result, clear_result);
```



