Hello World

Hello World Tutorial

This tutorial walks you through building your first E3 program from scratch. You'll learn how each component works and how they interact to create a secure, encrypted computation.

Make sure to complete the Quick Start guide first to get familiar with the basic workflow before diving into this detailed tutorial.

What We're Building

We'll create a simple E3 program that:

  1. Accepts two encrypted numbers from users
  2. Computes their sum using Fully Homomorphic Encryption
  3. Returns the encrypted result without ever decrypting the inputs

Prerequisites

Before starting, ensure you have:

Step 1: Project Setup

Create a new E3 project:

enclave init hello-world-e3
cd hello-world-e3

Let's examine the generated project structure:

hello-world-e3/
├── program/           # FHE computation logic (Rust)
├── contracts/         # Smart contracts (Solidity)
├── client/           # Frontend application (React/TypeScript)
├── server/           # Coordination server (TypeScript)
├── enclave.config.yaml # Enclave configuration
└── README.md         # Project documentation

Step 2: Understanding the FHE Program

The heart of your E3 program is in ./program/src/lib.rs. Let's examine the default implementation:

use e3_bfv_helpers::decode_bfv_params_arc;
use e3_compute_provider::FHEInputs;
use fhe_rs::bfv::Ciphertext;
use fhe_traits::{DeserializeParametrized, Serialize};
 
/// Implementation of the CiphertextProcessor function
pub fn fhe_processor(fhe_inputs: &FHEInputs) -> Vec<u8> {
    // Decode the FHE parameters
    let params = decode_bfv_params_arc(&fhe_inputs.params);
 
    // Start with zero (encrypted)
    let mut sum = Ciphertext::zero(&params);
    
    // Add each encrypted input to the sum
    for ciphertext_bytes in &fhe_inputs.ciphertexts {
        let ciphertext = Ciphertext::from_bytes(&ciphertext_bytes.0, &params).unwrap();
        sum += &ciphertext;  // Homomorphic addition
    }
 
    // Return the encrypted result
    sum.to_bytes()
}

Key Concepts:

  • FHEInputs: Contains encrypted data and parameters
  • Ciphertext: Encrypted values that can be computed on
  • Homomorphic operations: += works on encrypted data
  • No decryption: We never see the actual values

Step 3: Modifying the Computation

Let's create a more interesting computation. Replace the content of ./program/src/lib.rs:

use e3_bfv_helpers::decode_bfv_params_arc;
use e3_compute_provider::FHEInputs;
use fhe_rs::bfv::Ciphertext;
use fhe_traits::{DeserializeParametrized, Serialize};
 
/// Compute: (a + b) * 2
pub fn fhe_processor(fhe_inputs: &FHEInputs) -> Vec<u8> {
    let params = decode_bfv_params_arc(&fhe_inputs.params);
 
    // Get the two input ciphertexts
    if fhe_inputs.ciphertexts.len() != 2 {
        panic!("Expected exactly 2 inputs");
    }
 
    let a = Ciphertext::from_bytes(&fhe_inputs.ciphertexts[0].0, &params).unwrap();
    let b = Ciphertext::from_bytes(&fhe_inputs.ciphertexts[1].0, &params).unwrap();
 
    // Compute (a + b) * 2 homomorphically
    let sum = &a + &b;           // Add encrypted numbers
    let double = &sum + &sum;    // Multiply by 2 (via addition)
 
    double.to_bytes()
}

Step 4: Understanding the Configuration

The enclave.config.yaml file configures your development environment:

chains:
  - name: "hardhat"
    rpc_url: "ws://localhost:8545"
    contracts:
      e3_program: "0x9A676e781A523b5d0C0e43731313A708CB607508"
      # ... other contract addresses
 
nodes:
  cn1:  # Ciphernode 1
    address: "0xbDA5747bFD65F08deb54cb465eB87D40e51B197E"
    quic_port: 9201
    autonetkey: true
    autopassword: true
  # ... more nodes

Key Components:

  • Chains: Blockchain networks your E3 program uses
  • Contracts: Deployed smart contract addresses
  • Nodes: Ciphernodes that coordinate the E3 process

Step 5: Build and Test

Compile your modified program:

enclave program compile

Start the development environment:

pnpm dev:all

Step 6: Understanding the Client

The client application (in ./client/) handles:

  1. Encryption: User inputs → encrypted ciphertexts
  2. Submission: Publish encrypted data to the Enclave contract
  3. Result retrieval: Get the decrypted result from the Enclave contract

Step 7: Test Your Program

  1. Open http://localhost:3000 (opens in a new tab)
  2. Enter two numbers (e.g., 5 and 3)
  3. Submit the request
  4. Watch the result: (5 + 3) * 2 = 16

The computation happened entirely on encrypted data!

Step 8: Exploring Further

Now that you understand the basics, try these modifications:

Change the Computation

// Compute a² + b²
let a_squared = &a * &a;
let b_squared = &b * &b;
let result = &a_squared + &b_squared;

Add More Inputs

Modify your program to accept 3 or more encrypted inputs.

Update the UI

Customize the client application in ./client/src/ to match your computation.

Happy building with Enclave! 🚀

Next Steps

Ready to build more complex E3 programs? Continue with:

  1. Writing the Secure Process - Advanced FHE programming
  2. Writing the E3 Program Contract - Smart contract integration
  3. Setting Up the Server - Custom coordination logic