5 min read

全同态加密在AI/机器学习中的应用:Sunscreen Parasol 编译器和 SPF 框架

全同态加密架构下的隐私保护机器学习流程图

Sunscreen Tech:让隐私计算更易编程

Sunscreen 从底层密码方案发展到完整的 SPF(Secure Processing Framework),目标是实现”一处编写,到处运行”的跨链隐私计算。

1. 编译器:从 BFV 到 TFHE 的演进

Sunscreen 第一代 Parasol 编译器基于BFV,定义了自己的领域建模语言eDSL,所有的加密计算需要以eDSL开发。经过几年的演进,第二代编译器基于 LLVM 构建,并定义了虚拟的 Parasol 目标平台和指令集,开发方式也eDSL变成带宏标注的C语言程序。这降低了开发门槛的同时,也让编译的二进制文件具备了跨平台的能力。

第一代Parasol编译器代码库在Sunscreen-tech/sunscreen,第二代Parasol编译器基于LLVM和自定义的ISA,代码库在Sunscreen-tech/sunscreen-llvm

Sunscreen 早期主要支持 BFV 方案。为支持任意逻辑的通用计算,重心转向 TFHE (Torus FHE)。

TFHE 的快速自举能力允许在刷新噪声的同时执行逻辑运算。复杂的 AI 逻辑如分支判断和精确激活函数需要无限深度计算,而 TFHE 正好满足这一需求。

2. SPF (Secure Processing Framework) 的三层栈架构

Sunscreen 的 SPF(Secure Processing Framework)服务框架代码开源在Sunscreen-tech/spf。根据 Sunscreen 的最新技术架构,SPF 由三个相互协作的”技术栈”组成,实现了 FHE 计算与区块链共识层的解耦:

  • 开发栈 (Developer Stack):以基于 LLVM 的 Parasol 编译器为核心,允许开发者直接用 C 语言 编写程序并输出 ELF 对象文件。开发者只需标记隐私输入,编译器会自动处理复杂的参数选择和噪声评估。
  • 核心栈 (Core Stack):包含自定义的 PISA 指令集架构 和专门优化的虚拟处理器。它通过高度并行的 TFHE 库执行编译后的二进制文件,提取硬件级别的最大性能。
  • 控制栈 (Control Stack):它包含一个 Data Bus (数据总线) 作为”拉取预言机 (Pull Oracle)”,监听各链请求并将任务分发给 SPF。通过门限解密 (Threshold Decryption) 机制,去中心化委员会共同持有密钥分片,确保没有任何单一实体(包括 Sunscreen)能单方面访问数据。

SPF 面向 Web3 应用开发者,提供数据存储(上传、下载)、加密计算等服务。所有的重量计算都在 Sunscreen 管理的基础设施上进行,智能合约中仅保存二进制文件、密文等引用。

3. “一处编写,跨链互操作”的加密计算负载

SPF 在 Web3 环境下实现可验证的隐藏状态 (Verifiable Hidden State)。SPF 的特性包括:

  • 链无关性:由于计算在 SPF 内部独立运行,开发者编写的一段隐私 AI 逻辑可以通过简单的 Handle 挂载到 Ethereum、Solana 或其他任何链上。
  • 计算可验证性:集成 ZKP (零知识证明) 编译器,不仅用于验证加密输入的合法性,还用于证明 SPF 确实按照注册的程序二进制文件正确执行了计算。
  • 隐私 AI 代理:在这种架构下,AI 代理可以处理跨链的敏感数据(如私有交易策略或身份信息),而无需担心底层链的隐私限制。

使用 Parasol 开发 TFHE 加密计算应用

Parasol是Sunscreen的虚拟处理器,具有自己的ISA,支持TFHE在加密数据上的运算。Sunscreen提供基于LLVM的Parasol编译器编译修改过的程序到Parasol指令的ELF文件。这个ELF文件不能直接运行,需要通过SPF项目中的parasol_cpuparasol_runtime运行。

Parasol 工具链

虚拟Parasol处理器和运行环境依赖于Rust。如果还没有安装和配置Rust,需要通过Rustup安装Rust工具链。

Parasol编译器从Sunscreen-tech/sunscreen-llvm项目发布页下载。下载的tar包解压缩后放在合适的位置,如$HOME/.local/share/parasol-compiler-macos-aarch64-2025-11-24/(后续通过$PARASOL_LLVM_HOME替换)。

版本兼容性

Parasol 编译器与 parasol_cpu/parasol_runtime 需要保持版本一致。编译器版本与运行时库版本不匹配会导致链接错误或运行时崩溃。建议从同一 release 版本下载所有组件。

Parasol 计算程序

基于Parasol编写的程序几乎不用太大改动,只需要对需要在加密运行的数据上添加标注如:

  • [[clang::fhe_program]]标注函数
  • [[clang::encrypted]]标注参数
#include <parasol.h>
 
[[clang::fhe_program]]
uint8_t add([[clang::encrypted]] uint8_t a,
            [[clang::encrypted]] uint8_t b) {
  return a + b;
}

Parasol 程序构建和运行

Parasol 程序以类C风格编写,由Parasol编译器编译成二进制文件后,可以在本地通过Rust构建的Parasol工具链执行,也可以上传到Sunscreen的SPF服务中,并在智能合约或WASM中调用。

本地开发和测试需要安装Rust环境,并添加parasol_cpuparasol_runtime两个包。

$ cargo add parasol_cpu
$ cargo add parasol_runtime

按照Sunscreen官方教程编写Rust运行文件。编译这个Rust文件将静态链接Parasol相关的库到可执行文件,生成目标硬件平台的可执行文件。

性能注意事项

Parasol 运行时仅支持 CPU 执行。TFHE 计算非常密集,单个简单操作(如加法)可能需要数毫秒。对于复杂计算,建议在服务器环境运行,本地开发时使用小规模测试数据验证逻辑。

use parasol_cpu::{run_program, ArgsBuilder};
use parasol_runtime::{
    fluent::UInt8, ComputeKey, Encryption, SecretKey,
};
 
const FHE_FILE: &[u8] =
    include_bytes!("../fhe-programs/compiled/add");
 
fn main() {
    // Generate a secret key for the user. By default this ensures
    // 128 bit security.
    let secret_key =
        SecretKey::generate_with_default_params();
 
    // Generate a compute key for the user. These keys are used for
    // operations and do not give access to the plaintext data;
    // therefore, this key can safely be shared with another party.
    let compute_key =
        ComputeKey::generate_with_default_params(
            &secret_key,
        );
 
    // Get the default encryption parameters.
    let enc = Encryption::default();
 
    // Define the values we want to add. The sizes of the values
    // must match the size of the values defined in the
    // C TFHE program!
    let a = 2u8;
    let b = 7u8;
 
    let enc_a =
        UInt8::encrypt_secret(a as u128, &enc, &secret_key);
 
    let enc_b =
        UInt8::encrypt_secret(b as u128, &enc, &secret_key);
 
    // To pass arguments into the C program, we must use
    // the `ArgsBuilder` to construct the arguments.
    let arguments = ArgsBuilder::new()
        .arg(enc_a)
        .arg(enc_b)
        .return_value::<UInt8>();
 
    // Run the program.
    let encrypted_result = run_program(
        compute_key,
        FHE_FILE,
        "add",
        arguments,
    )
    .unwrap();
 
    // Decrypt the result.
    let result =
        encrypted_result.decrypt(&enc, &secret_key);
    println!("Encrypted {a} + {b} = {result}");
}

除此之外,Sunscreen也提供了Python客户端以在本地或服务端运行 FHE 程序,代码库位于Sunscreen-tech/spf-runner。这实际上是封装了SPF能力的Python库,底层仍然依赖于parasol_cpuparasol_runtime运行。

上面的简单程序可以通过如下的Python脚本运行。

import subprocess
from pathlib import Path
from sunscreen_fhe import KeySet, ParameterBuilder, read_outputs
 
# Generate keys
keys = KeySet.generate()
 
# Build parameters: encrypt inputs and declare output
params = (
    ParameterBuilder()
    .encrypt(100, bit_width=8, signed=False)
    .encrypt(50, bit_width=8, signed=False)
    .output(bit_width=8, size=1)
    .build(keys.public_key)
)
 
# Save compute key
Path("compute.key").write_bytes(keys.compute_key.to_bytes())
 
# Run the FHE program
result = subprocess.run(
    ["program_runner", "-e", "add", "-f", "add", "-k", "compute.key"],
    input=params.to_bytes(),
    capture_output=True,
    check=True,
)
 
# Decrypt result
outputs = read_outputs(result.stdout)
print(keys.decrypt(outputs[0], signed=False))  # 150

常见问题

链接错误

  • 确保编译器版本与 parasol_cpu/parasol_runtime 版本一致
  • 检查 Cargo.toml 中的依赖版本,使用 cargo update 同步

运行时 panic

  • 验证 ELF 文件路径正确
  • 检查函数名与 C 代码中的函数名完全匹配
  • 确认加密参数类型与程序定义一致

性能问题

  • TFHE 操作本身较慢,单个操作 1-10ms 是正常的
  • 使用 release 模式编译 Rust 代码 (cargo build --release)
  • 本地测试时使用小规模数据

使用 Sunscreen SPF服务

与在LatticaAI中部署Parasol编译二进制文件类似,Sunscreen围绕SPF提供托管的加密计算服务。

链上计算和链下计算

Sunscreen的SPF的框架提供了链下的加密数据算力基础设施,并仅支持CPU上运行。

展望:TFHE 通用计算支持和深度学习

深度学习中的非线性单元如 ReLU 需要分支和条件运算,这是 BFV、CKKS 等支持密文算术运算的方案所不擅长的。

Sunscreen 与 LatticaAI 的合作代表了一种趋势:应用全同态密码方案的保护隐私的机器学习开始逐步扩展到深度学习领域,尤其是以深度神经网络为代表的模型架构。虽然目前 Parasol TFHE编译器还不能支持GPU等加速硬件,但随着FHE 硬件加速的业界进展,扩展到深度学习是一个大的趋势。