Enclave is now The Interfold. Documentation is being updated.
Putting It All Together

Putting It All Together: A Complete Example

To solidify your understanding, let's walk through an example of building and deploying an E3 Program using RISC Zero.

Step 1: Set Up Development Environment

  • Install Required Tools:
    • Rust and Cargo
    • Node.js and pnpm
    • Foundry and Anvil for Ethereum development
    • RISC Zero toolchain

Step 2: Write the Secure Process

  • Implement the computation logic in Rust.
  • Use the Compute Provider package for handling inputs and Merkle tree verification.

Secure Process (Rust):

// src/main.rs
 
#![no_main]
#![no_std]
 
use e3_compute_provider::FHEInputs;
use fhe::bfv::{BfvParameters, Ciphertext};
use fhe_traits::{Deserialize, Serialize};
use std::sync::Arc;
 
risc0_zkvm_guest::entry!(main);
 
pub fn main() {
    // Receive encrypted inputs
    let fhe_inputs: FHEInputs = env::read();
 
    // Call your computation function
    let result = fhe_processor(&fhe_inputs);
 
    // Commit the result
    env::commit(&result);
}

Step 3: Implement Compute Provider

  • Implement the ComputeProvider trait for RISC Zero.
  • Handle proof generation and interaction with the zkVM.

Compute Provider Implementation:

pub struct Risc0Provider;
 
impl ComputeProvider for Risc0Provider {
    type Output = Risc0Output;
 
    fn prove(&self, input: &ComputeInput) -> Self::Output {
        // Set up the execution environment
        let env = ExecutorEnv::builder()
            .write(input)
            .unwrap()
            .build()
            .unwrap();
 
        // Generate the proof
        let receipt = default_prover()
            .prove_with_ctx(
                env,
                &VerifierContext::default(),
                VOTING_ELF,
                &ProverOpts::groth16(),
            )
            .unwrap()
            .receipt;
 
        // Extract and return the output
        Risc0Output {
            result: receipt.journal.decode().unwrap(),
            bytes: receipt.journal.bytes.clone(),
            seal: groth16::encode(receipt.inner.groth16().unwrap().seal.clone()).unwrap(),
        }
    }
}

Step 4: Write the E3 Program Contract

  • Define your E3 Program contract, integrating with the RISC Zero verifier.

E3 Program Contract (Solidity):

// SPDX-License-Identifier: LGPL-3.0-only
//
// This file is provided WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
pragma solidity >=0.8.27;
 
import {IEnclave, IE3Program} from "@enclave-e3/contracts/interfaces/IEnclave.sol";
import {IRiscZeroVerifier} from "risc0/IRiscZeroVerifier.sol";
 
contract MyE3Program is IE3Program {
    bytes32 public constant IMAGE_ID = /* Your Image ID */;
    bytes32 public constant ENCRYPTION_SCHEME_ID = /* Your Encryption Scheme ID */;
 
    IRiscZeroVerifier public verifier;
    IEnclave public enclave;
 
    constructor(
        IEnclave _enclave,
        IRiscZeroVerifier _verifier
    ) {
        enclave = _enclave;
        verifier = _verifier;
    }
 
    // Implement validate and verify functions as shown earlier
}

Step 5: Deploy Contracts

  • Deploy the Interfold contracts to your desired network.
  • Deploy your E3 Program contract and register it with the Interfold contract.

Step 6: Run Ciphernodes

  • Start Ciphernodes and ensure they are registered with the Interfold contract.

Step 7: Submit a Computation Request

  • Use your application or a script to submit a computation request to the Interfold contract.

Example (JavaScript):

// First approve the fee token
await FeeTokenContract.approve(EnclaveContract.address, computationFee)
 
// Then request the E3
await EnclaveContract.request({
  threshold: [thresholdMin, thresholdMax],
  inputWindow: [inputWindowStart, inputWindowEnd],
  e3Program: e3ProgramAddress,
  e3ProgramParams: e3ProgramParams,
  computeProviderParams: computeProviderParams,
  customParams: '0x',
})

Step 8: Submit Encrypted Inputs

  • Data Providers encrypt their inputs and submit them along with ZKPs.

Step 9: Execute Computation and Verify Proof

  • The Compute Provider executes the Secure Process.
  • The E3 Program contract verifies the computation proof on-chain.

Step 10: Ciphernodes Decrypt Result

  • Ciphernodes submit decryption shares.
  • The Decryption Verifier contract verifies the correctness of the decryption.

Step 11: Retrieve Final Result

  • Listen for the PlaintextOutputPublished event.
  • Retrieve the plaintext result from the Interfold contract.

Conclusion

By following this guide, you should now have a solid understanding of the Interfold and how to build your own E3 Programs. The Interfold provides a framework for privacy-preserving computations over encrypted data, enabling a new class of decentralized applications.

Key Takeaways:

  • The Interfold distributes trust and ensures data remains encrypted throughout computation.
  • The modular architecture allows for flexibility in choosing Compute Providers and designing computations.
  • The provided Compute Provider package simplifies integration and handles complex tasks like Merkle tree verification.

Additional Resources


Happy Building!

If you have any questions or need further assistance, feel free to reach out to Gnosis Guild (opens in a new tab), the initial development team building the Interfold.