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-e3Let'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 documentationStep 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::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::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: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
quic_port: 9201
autonetkey: true
autopassword: true
# ... more nodesKey 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 compileStart the development environment:
pnpm dev:allStep 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