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:
- Accepts two encrypted numbers from users
- Computes their sum using Fully Homomorphic Encryption
- Returns the encrypted result without ever decrypting the inputs
Prerequisites
Before starting, ensure you have:
- Enclave CLI installed
- Basic knowledge of Rust and TypeScript
- Rust, Docker, Node.js, and pnpm installed
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(¶ms);
// Add each encrypted input to the sum
for ciphertext_bytes in &fhe_inputs.ciphertexts {
let ciphertext = Ciphertext::from_bytes(&ciphertext_bytes.0, ¶ms).unwrap();
sum += &ciphertext; // Homomorphic addition
}
// Return the encrypted result
sum.to_bytes()
}
Key Concepts:
FHEInputs
: Contains encrypted data and parametersCiphertext
: 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, ¶ms).unwrap();
let b = Ciphertext::from_bytes(&fhe_inputs.ciphertexts[1].0, ¶ms).unwrap();
// Compute (a + b) * 2 homomorphically
let sum = &a + &b; // Add encrypted numbers
let double = &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:
- Encryption: User inputs → encrypted ciphertexts
- Submission: Publish encrypted data to the Enclave contract
- Result retrieval: Get the decrypted result from the Enclave contract
Step 7: Test Your Program
- Open http://localhost:3000 (opens in a new tab)
- Enter two numbers (e.g., 5 and 3)
- Submit the request
- 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:
- Writing the Secure Process - Advanced FHE programming
- Writing the E3 Program Contract - Smart contract integration
- Setting Up the Server - Custom coordination logic