Clean up: Move Go FHE implementation to lux/fhe

- Remove old Go FHE code (now in lux/fhe)
- Remove old Zama compatibility layers
- Update CI for TypeScript/JS SDK only
- This repo is now purely the @luxfhe npm package ecosystem
This commit is contained in:
2026-01-02 10:53:28 -08:00
parent 9206cb2de1
commit ce2fee8b1b
2509 changed files with 461227 additions and 624796 deletions
+63 -216
View File
@@ -2,263 +2,110 @@ name: CI
on:
push:
branches: [main]
branches: [main, master]
pull_request:
branches: [main]
branches: [main, master]
jobs:
test-go:
name: Go Tests (${{ matrix.go-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
go-version: ['1.25']
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Download dependencies
run: go mod download
- name: Build
env:
CGO_ENABLED: '0'
run: |
go build ./...
go build ./server/standalone/
- name: Test (Unix)
if: runner.os != 'Windows'
env:
CGO_ENABLED: '0'
run: go test -v -timeout 30m -coverprofile=coverage.out .
- name: Test (Windows)
if: runner.os == 'Windows'
env:
CGO_ENABLED: '0'
run: go test -v -timeout 30m .
- name: Upload coverage
if: matrix.os == 'ubuntu-latest'
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage.out
test-cgo:
name: CGO Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build CGO packages
run: |
# Test that CGO packages compile (they need external libs at runtime)
CGO_ENABLED=1 go build -v ./cgo ./gpu ./server ./cmd/fhe-server 2>&1 || echo "CGO build requires external libraries - expected in CI"
test-c:
name: C SDK
build-sdk:
name: Build SDK
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build C shared library
run: |
mkdir -p sdk/c/lib
CGO_ENABLED=1 go build -buildmode=c-shared -o sdk/c/lib/libluxfhe.so ./sdk/c/src/luxfhe.go
- name: Verify library exports
run: |
nm -D sdk/c/lib/libluxfhe.so | grep luxfhe | head -20
- name: Upload C library
uses: actions/upload-artifact@v4
with:
name: libluxfhe-linux
path: sdk/c/lib/libluxfhe.so
test-wasm:
name: WASM SDK
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build WASM
run: |
GOOS=js GOARCH=wasm go build -o sdk/wasm/luxfhe.wasm ./sdk/wasm/main.go
ls -lh sdk/wasm/luxfhe.wasm
- name: Upload WASM
uses: actions/upload-artifact@v4
with:
name: luxfhe-wasm
path: sdk/wasm/luxfhe.wasm
test-typescript:
name: TypeScript SDK (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: ['18', '20', '22']
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
node-version: '20'
cache: 'npm'
cache-dependency-path: js/v2-sdk/package-lock.json
- name: Install dependencies
working-directory: sdk/typescript
working-directory: js/v2-sdk
run: npm ci
- name: Type check
working-directory: sdk/typescript
run: npm run typecheck
- name: Build
working-directory: sdk/typescript
working-directory: js/v2-sdk
run: npm run build
- name: Upload TypeScript dist
if: matrix.node-version == '22'
uses: actions/upload-artifact@v4
with:
name: luxfhe-ts
path: sdk/typescript/dist
test-rust:
name: Rust SDK
runs-on: ubuntu-latest
needs: test-c
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Download C library
uses: actions/download-artifact@v4
with:
name: libluxfhe-linux
path: sdk/c/lib
- name: Install libclang for bindgen
run: sudo apt-get update && sudo apt-get install -y libclang-dev
- name: Check Rust bindings
working-directory: sdk/rust
run: cargo check
- name: Build Rust bindings
working-directory: sdk/rust
- name: Run unit tests
working-directory: js/v2-sdk
run: npm test -- --reporter=verbose --testTimeout=60000
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/sdk/c/lib
run: cargo build --release
SKIP_LOCAL_ENV: true
test-python:
name: Python SDK (${{ matrix.python-version }})
build-hardhat-plugin:
name: Build Hardhat Plugin
runs-on: ubuntu-latest
needs: test-c
strategy:
fail-fast: false
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
python-version: ${{ matrix.python-version }}
node-version: '20'
cache: 'npm'
cache-dependency-path: plugins/hardhat/package-lock.json
- name: Download C library
uses: actions/download-artifact@v4
with:
name: libluxfhe-linux
path: sdk/c/lib
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Install forge-std
working-directory: plugins/hardhat
run: |
mkdir -p lib
forge install foundry-rs/forge-std --no-commit --root .
- name: Install dependencies
working-directory: sdk/python
run: |
pip install cffi pytest
pip install -e .
working-directory: plugins/hardhat
run: npm ci
- name: Build
working-directory: plugins/hardhat
run: npm run build
- name: Run tests
working-directory: sdk/python
env:
LD_LIBRARY_PATH: ${{ github.workspace }}/sdk/c/lib
run: pytest -v tests/
working-directory: plugins/hardhat
run: npm test
benchmark:
name: Benchmark
build-permit:
name: Build Permit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
go-version: '1.25'
node-version: '20'
cache: 'npm'
cache-dependency-path: js/permit/package-lock.json
- name: Run benchmarks
env:
CGO_ENABLED: '0'
run: go test -bench=BenchmarkLattice -benchmem -run=^$ . | tee benchmark.txt
- name: Install dependencies
working-directory: js/permit
run: npm ci
- name: Upload benchmark
uses: actions/upload-artifact@v4
with:
name: benchmark
path: benchmark.txt
- name: Build
working-directory: js/permit
run: npm run build
lint:
name: Lint
build-wasm:
name: Build WASM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
go-version: '1.25'
node-version: '20'
cache: 'npm'
cache-dependency-path: packages/wasm/package-lock.json
- name: Run go vet
env:
CGO_ENABLED: '0'
run: go vet ./...
- name: Install dependencies
working-directory: packages/wasm
run: npm ci
- name: Run go fmt check
run: |
if [ "$(gofmt -s -l . | wc -l)" -gt 0 ]; then
echo "The following files need to be formatted:"
gofmt -s -l .
exit 1
fi
- name: Build
working-directory: packages/wasm
run: npm run build
-73
View File
@@ -1,73 +0,0 @@
name: Docker Publish
on:
push:
branches: [main, master]
tags: ['v*']
pull_request:
branches: [main, master]
workflow_dispatch:
env:
REGISTRY: ghcr.io
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- target: server
image: luxfi/fhe/server
- target: gateway
image: luxfi/fhe/gateway
- target: worker
image: luxfi/fhe/worker
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ matrix.image }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push ${{ matrix.target }}
uses: docker/build-push-action@v5
with:
context: .
target: ${{ matrix.target }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=${{ matrix.target }}
cache-to: type=gha,mode=max,scope=${{ matrix.target }}
-66
View File
@@ -1,66 +0,0 @@
name: Deploy Docs to GitHub Pages
on:
push:
branches: [main]
paths:
- 'docs/**'
- '.github/workflows/docs.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'pnpm'
cache-dependency-path: docs/pnpm-lock.yaml
- name: Install dependencies
working-directory: docs
run: pnpm install
- name: Build docs
working-directory: docs
run: pnpm build
- name: Setup Pages
uses: actions/configure-pages@v5
with:
enablement: true
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+152
View File
@@ -0,0 +1,152 @@
name: Publish to NPM
on:
release:
types: [published]
workflow_dispatch:
inputs:
package:
description: 'Package to publish'
required: true
type: choice
options:
- all
- sdk
- hardhat-plugin
- permit
- wasm
- foundry-mocks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
jobs:
publish-wasm:
name: Publish @luxfhe/wasm
runs-on: ubuntu-latest
if: github.event_name == 'release' || github.event.inputs.package == 'all' || github.event.inputs.package == 'wasm'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
working-directory: packages/wasm
run: npm ci
- name: Build
working-directory: packages/wasm
run: npm run build
- name: Publish
working-directory: packages/wasm
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-sdk:
name: Publish @luxfhe/sdk
runs-on: ubuntu-latest
needs: publish-wasm
if: always() && (github.event_name == 'release' || github.event.inputs.package == 'all' || github.event.inputs.package == 'sdk')
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
working-directory: js/v2-sdk
run: npm ci
- name: Build
working-directory: js/v2-sdk
run: npm run build
- name: Publish
working-directory: js/v2-sdk
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-permit:
name: Publish @luxfhe/permit
runs-on: ubuntu-latest
needs: publish-wasm
if: always() && (github.event_name == 'release' || github.event.inputs.package == 'all' || github.event.inputs.package == 'permit')
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
working-directory: js/permit
run: npm ci
- name: Build
working-directory: js/permit
run: npm run build
- name: Publish
working-directory: js/permit
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-foundry-mocks:
name: Publish @luxfhe/foundry-mocks
runs-on: ubuntu-latest
if: github.event_name == 'release' || github.event.inputs.package == 'all' || github.event.inputs.package == 'foundry-mocks'
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Publish
working-directory: mocks/foundry
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-hardhat-plugin:
name: Publish @luxfhe/hardhat-plugin
runs-on: ubuntu-latest
needs: [publish-sdk, publish-foundry-mocks]
if: always() && (github.event_name == 'release' || github.event.inputs.package == 'all' || github.event.inputs.package == 'hardhat-plugin')
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
working-directory: plugins/hardhat
run: npm ci
- name: Build
working-directory: plugins/hardhat
run: npm run build
- name: Publish
working-directory: plugins/hardhat
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
-304
View File
@@ -1,304 +0,0 @@
name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g., v0.1.0)'
required: true
type: string
permissions:
contents: write
jobs:
build-binaries:
name: Build (${{ matrix.os }}, ${{ matrix.arch }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
# Linux
- os: linux
arch: amd64
runner: ubuntu-latest
ext: ''
- os: linux
arch: arm64
runner: ubuntu-latest
ext: ''
# macOS
- os: darwin
arch: amd64
runner: macos-latest
ext: ''
- os: darwin
arch: arm64
runner: macos-latest
ext: ''
# Windows
- os: windows
arch: amd64
runner: windows-latest
ext: '.exe'
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build binaries
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
CGO_ENABLED: '0'
run: |
# Pure Go binaries (no CGO required)
go build -ldflags="-s -w" -o luxfhe-server-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} ./server/standalone/
go build -ldflags="-s -w" -o luxfhe-gateway-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} ./cmd/fhe-gateway/
go build -ldflags="-s -w" -o luxfhe-worker-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }} ./cmd/fhe-worker/
- name: Upload binaries
uses: actions/upload-artifact@v4
with:
name: luxfhe-${{ matrix.os }}-${{ matrix.arch }}
path: |
luxfhe-server-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}
luxfhe-gateway-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}
luxfhe-worker-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.ext }}
build-c-libraries:
name: C Library (${{ matrix.os }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- os: linux
runner: ubuntu-latest
lib: libluxfhe.so
- os: darwin
runner: macos-latest
lib: libluxfhe.dylib
- os: windows
runner: windows-latest
lib: luxfhe.dll
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build C shared library
shell: bash
run: |
mkdir -p dist
CGO_ENABLED=1 go build -buildmode=c-shared -o dist/${{ matrix.lib }} ./sdk/c/src/luxfhe.go
- name: Upload C library
uses: actions/upload-artifact@v4
with:
name: libluxfhe-${{ matrix.os }}
path: dist/
build-wasm:
name: WASM Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.25'
- name: Build WASM
run: |
mkdir -p dist
GOOS=js GOARCH=wasm go build -o dist/luxfhe.wasm ./sdk/wasm/main.go
# wasm_exec.js may not exist in Go 1.25 toolchain, download if needed
if [ -f "$(go env GOROOT)/misc/wasm/wasm_exec.js" ]; then
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" dist/
else
curl -sL "https://raw.githubusercontent.com/golang/go/go$(go version | awk '{print $3}' | sed 's/go//')/misc/wasm/wasm_exec.js" -o dist/wasm_exec.js
fi
- name: Upload WASM
uses: actions/upload-artifact@v4
with:
name: luxfhe-wasm
path: dist/
build-typescript:
name: TypeScript SDK
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
- name: Install and build
working-directory: sdk/typescript
run: |
npm ci
npm run build
- name: Package
working-directory: sdk/typescript
run: npm pack
- name: Publish to npm
if: startsWith(github.ref, 'refs/tags/v')
continue-on-error: true # Don't fail if version already exists
working-directory: sdk/typescript
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Upload package
uses: actions/upload-artifact@v4
with:
name: luxfhe-typescript
path: sdk/typescript/*.tgz
publish-python:
name: Python SDK
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install build tools
run: pip install build twine
- name: Build package
working-directory: sdk/python
run: python -m build
- name: Publish to PyPI
continue-on-error: true # Don't fail if no token or version exists
working-directory: sdk/python
run: twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
create-release:
name: Create Release
runs-on: ubuntu-latest
needs: [build-binaries, build-c-libraries, build-wasm, build-typescript]
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release
# Binaries
for dir in artifacts/luxfhe-*; do
if [ -d "$dir" ]; then
name=$(basename "$dir")
if [[ "$name" == luxfhe-linux-* ]] || [[ "$name" == luxfhe-darwin-* ]] || [[ "$name" == luxfhe-windows-* ]]; then
for f in "$dir"/*; do
cp "$f" "release/"
done
fi
fi
done
# C libraries
for os in linux darwin windows; do
if [ -d "artifacts/libluxfhe-$os" ]; then
tar -czvf "release/libluxfhe-$os.tar.gz" -C "artifacts/libluxfhe-$os" .
fi
done
# WASM
if [ -d "artifacts/luxfhe-wasm" ]; then
tar -czvf "release/luxfhe-wasm.tar.gz" -C "artifacts/luxfhe-wasm" .
fi
# TypeScript
if [ -d "artifacts/luxfhe-typescript" ]; then
cp artifacts/luxfhe-typescript/*.tgz release/
fi
ls -la release/
- name: Generate checksums
run: |
cd release
sha256sum * > checksums.txt
cat checksums.txt
- name: Get tag name
id: tag
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
else
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.tag.outputs.tag }}
name: LuxFHE ${{ steps.tag.outputs.tag }}
body: |
## LuxFHE ${{ steps.tag.outputs.tag }}
Pure Go implementation of TFHE (Torus Fully Homomorphic Encryption).
### Downloads
#### Binaries (Pure Go - no dependencies)
| Platform | Architecture | Server | Gateway | Worker |
|----------|--------------|--------|---------|--------|
| Linux | amd64 | `luxfhe-server-linux-amd64` | `luxfhe-gateway-linux-amd64` | `luxfhe-worker-linux-amd64` |
| Linux | arm64 | `luxfhe-server-linux-arm64` | `luxfhe-gateway-linux-arm64` | `luxfhe-worker-linux-arm64` |
| macOS | amd64 | `luxfhe-server-darwin-amd64` | `luxfhe-gateway-darwin-amd64` | `luxfhe-worker-darwin-amd64` |
| macOS | arm64 | `luxfhe-server-darwin-arm64` | `luxfhe-gateway-darwin-arm64` | `luxfhe-worker-darwin-arm64` |
| Windows | amd64 | `luxfhe-server-windows-amd64.exe` | `luxfhe-gateway-windows-amd64.exe` | `luxfhe-worker-windows-amd64.exe` |
#### SDK Libraries
- `libluxfhe-linux.tar.gz` - C shared library for Linux
- `libluxfhe-darwin.tar.gz` - C shared library for macOS
- `libluxfhe-windows.tar.gz` - C DLL for Windows
- `luxfhe-wasm.tar.gz` - WebAssembly build
- `luxfhe-*.tgz` - TypeScript/JavaScript SDK
#### GPU-Accelerated Server
Build from source with CGO and [luxcpp/fhe](https://github.com/luxcpp/fhe):
```bash
CGO_ENABLED=1 go build ./cmd/fhe-server
```
### Verification
Verify downloads with checksums:
```bash
sha256sum -c checksums.txt
```
files: release/*
draft: false
prerelease: ${{ contains(steps.tag.outputs.tag, '-') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+66 -47
View File
@@ -1,65 +1,84 @@
# Binaries
*.exe
*.exe~
*.dll
*.so
*.dylib
# Dependencies
node_modules/
.pnpm-store/
.yarn/cache/
.yarn/unplugged/
# Test binary
*.test
# Build outputs
dist/
build/
out/
.next/
.nuxt/
.output/
# Output of go coverage tool
*.out
coverage.txt
# Dependency directories
vendor/
# Cache
.cache/
*.cache
.turbo/
.parcel-cache/
# IDE
.idea/
.vscode/
*.swp
*.swo
# macOS
.DS_Store
# Docs
docs/.next/
docs/out/
docs/node_modules/
# Environment
.env
.env.local
.env.*.local
!.env.example
# Profiling
*.prof
*.pprof
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Build artifacts
bin/
dist/
# Testing
coverage/
.nyc_output/
# TypeScript SDK
ts/node_modules/
ts/dist/
# Rust bindings
rust/target/
# Rust
target/
Cargo.lock
!core/*/Cargo.lock
!research/*/Cargo.lock
!wasm/*/Cargo.lock
# Python
python/__pycache__/
python/*.egg-info/
python/build/
python/.venv/
__pycache__/
*.py[cod]
*$py.class
.Python
*.egg-info/
.eggs/
*.egg
.venv/
venv/
ENV/
# C library binaries (keep headers)
c/lib/*.so
c/lib/*.dylib
c/lib/*.a
c/examples/cpp_test
# Go
*.exe
*.exe~
*.dll
*.so
*.dylib
# WASM binaries (large, build from source)
wasm/*.wasm
ts/wasm/*.wasm
target/
*.o
*.a
# Hardhat/Foundry
cache/
artifacts/
typechain/
typechain-types/
forge-cache/
# Misc
*.bak
*.tmp
*.temp
.git-backup/
python-sdk
ml-sdk
-216
View File
@@ -1,216 +0,0 @@
# FHE Benchmarks
Benchmarks for the Lux FHE implementation on Apple M1 Max (ARM64).
## Summary Comparison
| Operation | Pure Go (Lattice) | OpenFHE (CGO) | Winner |
|-----------|-------------------|---------------|--------|
| SecretKey Gen | 41.7 µs | 14.4 µs | CGO 2.9x |
| BootstrapKey Gen | 131.9 ms | 2413 ms | **Go 18x** |
| Encrypt Bit | 20.8 µs | 27.7 µs | Go 1.3x |
| Decrypt Bit | 4.5 µs | 1.4 µs | CGO 3.2x |
| NOT | 1.2 µs | 1.4 µs | ~Same |
| AND | 51.3 ms | 56.2 ms | Go 1.10x |
| OR | 52.3 ms | 56.4 ms | Go 1.08x |
| XOR | 51.2 ms | 56.3 ms | **Go 1.10x** |
| NAND | 52.0 ms | 56.4 ms | Go 1.08x |
| NOR | 52.2 ms | 56.3 ms | Go 1.08x |
| XNOR | 51.0 ms | 57.6 ms | **Go 1.13x** |
**Key Findings:**
- Pure Go bootstrap key gen is **18x faster** than OpenFHE (132ms vs 2.4s)
- Pure Go is faster for ALL gates (~51ms vs ~56ms)
- **XOR/XNOR optimized** to use single bootstrap (matching OpenFHE algorithm)
- Decrypt is faster with OpenFHE (1.4µs vs 4.5µs)
---
## Pure Go (Lattice) Backend
### Key Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| SecretKey Gen | 41.7 µs | 15.6 KB | 21 |
| PublicKey Gen | 17.4 µs | 11.9 KB | 22 |
| BootstrapKey Gen | 131.9 ms | 82.4 MB | 151K |
### Boolean Gate Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Encrypt Bit | 20.8 µs | 16.0 KB | 29 |
| Decrypt Bit | 4.5 µs | 4.7 KB | 8 |
| NOT | 1.2 µs | 8.9 KB | 11 |
| AND | 51.3 ms | 1.2 MB | 38K |
| OR | 52.3 ms | 1.2 MB | 38K |
| NAND | 52.0 ms | 1.2 MB | 38K |
| NOR | 52.2 ms | 1.2 MB | 38K |
| XOR | 51.2 ms | 1.2 MB | 38K |
| XNOR | 51.0 ms | 1.2 MB | 38K |
| MUX | 158.4 ms | 3.6 MB | 114K |
### Multi-Input Gate Operations
| Operation | Time | Memory | Allocs | Notes |
|-----------|------|--------|--------|-------|
| AND3 | 117.2 ms | 2.4 MB | 76K | 2 bootstraps |
| OR3 | 118.7 ms | 2.4 MB | 76K | 2 bootstraps |
| MAJORITY | 58.6 ms | 1.2 MB | 38K | **1 bootstrap** |
**MAJORITY optimization:** Uses single bootstrap since threshold at 0 correctly
separates 0-1 true inputs (negative sum) from 2-3 true inputs (positive sum).
### Integer Encryption/Decryption
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Encrypt 8-bit | 166.8 µs | 128 KB | 234 |
| Encrypt 16-bit | 326.6 µs | 256 KB | 466 |
| Encrypt 32-bit | 663.5 µs | 512 KB | 930 |
| Decrypt 8-bit | 36.5 µs | 37.9 KB | 64 |
| Decrypt 16-bit | 74.0 µs | 75.8 KB | 128 |
### Integer Arithmetic (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Add | 3.50 s | 81.2 MB | 2.6M |
| Sub | 5.20 s | 115.1 MB | 3.6M |
| ScalarAdd | 1.61 s | 36.2 MB | 1.1M |
### Integer Comparisons (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Eq | 1.74 s | 37.3 MB | 1.2M |
| Lt | 2.91 s | 64.0 MB | 2.0M |
| Le | 4.52 s | 102.8 MB | 3.2M |
| Gt | 2.78 s | 64.1 MB | 2.0M |
| Min | 4.00 s | 93.1 MB | 2.9M |
| Max | 4.01 s | 93.0 MB | 2.9M |
### Bitwise Operations (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| AND | 420.5 ms | 9.7 MB | 306K |
| OR | 429.2 ms | 9.6 MB | 304K |
| XOR | 1.45 s | 29.0 MB | 916K |
| NOT | 10.5 µs | 71.0 KB | 90 |
| Shl | 9.9 µs | 35.4 KB | 42 |
| Shr | 9.6 µs | 35.4 KB | 42 |
### Other Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Select (8-bit) | 1.27 s | 29.0 MB | 914K |
| CastTo (8→16) | 40.1 µs | 141.4 KB | 162 |
| PublicEncrypt 8-bit | 308.2 µs | 134.3 KB | 274 |
| PublicEncrypt 16-bit | 597.9 µs | 268.6 KB | 546 |
### Serialization
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Serialize Ciphertext | 14.4 µs | 34.9 KB | 98 |
| Deserialize Ciphertext | 20.3 µs | 28.6 KB | 255 |
| Serialize 8-bit Int | 126.8 µs | 430.8 KB | 800 |
| Serialize 16-bit Int | 255.9 µs | 873.8 KB | 1593 |
### RNG
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| RandomUint 8-bit | 173.0 µs | 128.1 KB | 235 |
| RandomUint 16-bit | 340.9 µs | 256.1 KB | 467 |
---
## OpenFHE (CGO) Backend
Benchmarks from OpenFHE 1.2.x with GINX bootstrapping method.
### Key Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| SecretKey Gen | 14.4 µs | 8 B | 1 |
| BootstrapKey Gen | 2413 ms | 0 B | 0 |
### Boolean Gate Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Encrypt Bit | 27.7 µs | 8 B | 1 |
| Decrypt Bit | 1.4 µs | 0 B | 0 |
| NOT | 1.4 µs | 8 B | 1 |
| AND | 56.2 ms | 8 B | 1 |
| OR | 56.4 ms | 8 B | 1 |
| XOR | 56.3 ms | 8 B | 1 |
| NAND | 56.4 ms | 8 B | 1 |
| NOR | 56.3 ms | 8 B | 1 |
| XNOR | 57.6 ms | 8 B | 1 |
---
## Running Benchmarks
### Pure Go Backend
```bash
cd /path/to/lux/tfhe
# All benchmarks
go test -bench=. -benchmem -run=^$ .
# Only lattice benchmarks
go test -bench=BenchmarkLattice -benchmem -run=^$ .
# With memory profiling
go test -bench=BenchmarkLatticeAdd8 -benchmem -memprofile=mem.prof -run=^$ .
```
### OpenFHE (CGO) Backend
```bash
cd /path/to/lux/fhe/go/tfhe
# Set OpenFHE paths
export CGO_CXXFLAGS='-I/path/to/openfhe/include -I/path/to/openfhe/include/openfhe -I/path/to/openfhe/include/openfhe/core'
export CGO_LDFLAGS='-L/path/to/openfhe/lib -lOPENFHEbinfhe -lOPENFHEcore -lOPENFHEpke -Wl,-rpath,/path/to/openfhe/lib'
go test -bench=. -benchmem -run=^$ .
```
---
## Performance Notes
1. **Bootstrap Key Generation**: Pure Go is 18x faster (132ms vs 2.4s). OpenFHE may use different parameter sets.
2. **All Boolean gates**: Pure Go is ~10% faster (~51ms vs ~56ms)
3. **XOR/XNOR optimized**: Now uses OpenFHE's `2*(ct1+ct2)` algorithm with single bootstrap
4. **NOT** is essentially free in both implementations (~1.4µs) - no bootstrapping needed
5. **Decrypt**: OpenFHE is faster (1.4µs vs 4.5µs)
6. **Memory**: OpenFHE uses ~8 bytes per op (pointer only), Go tracks more allocations
## Recommendations
| Use Case | Recommended Backend |
|----------|---------------------|
| Startup-sensitive (key gen) | Pure Go |
| All boolean circuits | Pure Go (faster) |
| No C++ dependencies needed | Pure Go |
| Maximum integer performance | OpenFHE (GPU future) |
## Hardware
- **CPU**: Apple M1 Max
- **Architecture**: ARM64
- **Cores**: 10 (8P + 2E)
- **Go Version**: 1.22+
- **OpenFHE Version**: 1.2.x
---
*Benchmarks run on December 27, 2024*
-50
View File
@@ -1,50 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Changed
- Renamed module from `github.com/luxfi/tfhe` to `github.com/luxfi/fhe`
- Updated Go version requirement to 1.23
### Fixed
- AND/NAND gate test polynomials now use correct threshold comparison
- Carry refresh in ScalarAdd prevents noise accumulation
- WASM SDK build errors resolved
- Code formatting with gofmt
### Added
- Comprehensive test coverage for FHE operations
- Pure Go mode tests (`CGO_ENABLED=0`)
- CGO mode tests with GPU acceleration stubs
- Integer arithmetic tests (Add, Sub, Mul)
- BigInt type tests (uint128, uint160, uint256)
- Serialization tests for keys
- RNG tests for encrypted random number generation
- Adversarial and fuzz tests
## [0.1.0] - 2025-01-01
### Added
- Initial FHE implementation based on TFHE scheme
- Boolean FHE operations (AND, OR, XOR, NOT, NAND, NOR, XNOR, MUX)
- Integer FHE types (FheUint4 through FheUint256)
- Bitwise integer operations with ripple-carry arithmetic
- ShortInt operations with LUT-based evaluation
- Key generation (SecretKey, PublicKey, BootstrapKey)
- Serialization support for all key types
- Multi-SDK support:
- C shared library
- Python bindings (via CFFI)
- Rust bindings (via bindgen)
- TypeScript/WASM support
- GPU acceleration framework (CUDA via MLX)
- Server mode for FHE-as-a-service
- Comprehensive benchmarks and documentation
[Unreleased]: https://github.com/luxfi/fhe/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/luxfi/fhe/releases/tag/v0.1.0
-80
View File
@@ -1,80 +0,0 @@
# Lux FHE - Multi-target Dockerfile
# Builds: server (pure-go), gateway, worker
FROM golang:1.23-alpine AS builder
WORKDIR /app
# Install build dependencies
RUN apk add --no-cache git ca-certificates
# Enable toolchain auto-download for newer Go versions
ENV GOTOOLCHAIN=auto
# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download
# Copy source
COPY . .
# Build binaries (pure Go, no CGO)
RUN CGO_ENABLED=0 GOOS=linux go build -o /bin/fhe-gateway ./cmd/fhe-gateway/
RUN CGO_ENABLED=0 GOOS=linux go build -o /bin/fhe-worker ./cmd/fhe-worker/
# Build pure-go server (creates standalone server without C acceleration)
RUN CGO_ENABLED=0 GOOS=linux go build -tags purgo -o /bin/fhe-server ./server/standalone/
# =============================================================================
# Server image (pure Go implementation)
# =============================================================================
FROM alpine:3.19 AS server
RUN apk add --no-cache ca-certificates curl
WORKDIR /app
COPY --from=builder /bin/fhe-server .
RUN mkdir -p /app/data
EXPOSE 8448
ENTRYPOINT ["./fhe-server"]
CMD ["-addr", ":8448"]
# =============================================================================
# Gateway image
# =============================================================================
FROM alpine:3.19 AS gateway
RUN apk add --no-cache ca-certificates curl
WORKDIR /app
COPY --from=builder /bin/fhe-gateway .
RUN mkdir -p /app/data
EXPOSE 8080
ENTRYPOINT ["./fhe-gateway"]
CMD ["-http", ":8080"]
# =============================================================================
# Worker image
# =============================================================================
FROM alpine:3.19 AS worker
RUN apk add --no-cache ca-certificates curl
WORKDIR /app
COPY --from=builder /bin/fhe-worker .
RUN mkdir -p /app/data
EXPOSE 9090
ENTRYPOINT ["./fhe-worker"]
CMD ["-workers", "4"]
+387 -549
View File
File diff suppressed because it is too large Load Diff
+191
View File
@@ -0,0 +1,191 @@
# Lux FHE Repository Migration Plan
## Overview
Restructure `/Users/z/work/luxfhe` monorepo into separate top-level repos under `github.com/luxfhe/` organization.
## Current Structure -> Target Repos
| Current Directory | Target Repo | Package Name | Description |
|-------------------|-------------|--------------|-------------|
| `contracts/` | `luxfhe/contracts` | `@luxfhe/contracts` | Core FHE Solidity contracts |
| `js/v1-sdk/` | `luxfhe/v1-sdk` | `@luxfhe/v1-sdk` | Standard TFHE SDK (single-key) |
| `js/v2-sdk/` | `luxfhe/v2-sdk` | `@luxfhe/v2-sdk` | Threshold TFHE SDK (network) |
| `js/permit/` | `luxfhe/permit` | `@luxfhe/permit` | Permit signing utilities |
| `mocks/` | `luxfhe/mocks` | `@luxfhe/mocks` | Mock contracts for testing |
| `examples/` | `luxfhe/examples` | - | Example applications (monorepo) |
| `templates/` | `luxfhe/templates` | - | Project starter templates |
| `docs/` | `luxfhe/docs` | - | Documentation sites |
| `research/` | `luxfhe/research` | - | Research projects |
| `scaffold-eth/` | `luxfhe/scaffold-eth` | - | Scaffold-ETH integration |
| `wasm/` | `luxfhe/wasm-sdk` | `@luxfhe/wasm-sdk` | Rust WASM SDK |
| `proto/` | `luxfhe/proto` | - | Protocol buffer definitions |
| `plugins/hardhat/` | `luxfhe/hardhat-plugin` | `@luxfhe/hardhat-plugin` | Hardhat plugin (CoFHE) |
| `plugins/remix/` | `luxfhe/remix-plugin` | `@luxfhe/remix-plugin` | Remix IDE plugin |
| `hardhat-plugin/` | (merge into hardhat-plugin) | - | Duplicate hardhat plugin root |
| `sdk/fhe/` | `luxfhe/fhe-sdk` | `@luxfhe/fhe-sdk` | CoFHE SDK monorepo |
| `sdk/relayer/` | `luxfhe/relayer` | `@luxfhe/relayer` | Transaction relayer |
| `ml/` | `luxfhe/ml` | - | FHE ML extensions |
| `tests/` | (distribute to each repo) | - | E2E test suites |
## Dependency Graph
```
@luxfhe/contracts
|
+-------------+-------------+
| | |
@luxfhe/v1-sdk @luxfhe/v2-sdk @luxfhe/permit
| | |
+------+------+ |
| |
@luxfhe/hardhat-plugin -----+
|
@luxfhe/mocks
```
### Core Dependencies (shared)
1. **@luxfhe/contracts** (no internal deps)
- External: @openzeppelin/contracts, hardhat
2. **@luxfhe/v1-sdk** (no internal deps)
- External: ethers, node-tfhe, tfhe, node-tkms, tkms
3. **@luxfhe/v2-sdk** (no internal deps)
- External: ethers, node-tfhe, tfhe, zustand, zod
4. **@luxfhe/permit** (no internal deps)
- External: ethers, node-tfhe, tweetnacl
5. **@luxfhe/hardhat-plugin**
- Internal: @luxfhe/contracts (via peerDeps), @luxfhe/v1-sdk or v2-sdk
- External: hardhat, ethers
6. **@luxfhe/mocks**
- Internal: @luxfhe/contracts
- External: hardhat, foundry
## Package.json Changes Required
### 1. contracts/package.json
```diff
- "repository": { "url": "https://github.com/luxfhe/contracts.git" }
+ "repository": { "url": "https://github.com/luxfhe/contracts.git" }
// Already correct
```
### 2. js/v1-sdk/package.json
```diff
- "repository": { "url": "git+https://github.com/luxfhe/v1-sdk.git" }
+ "repository": { "url": "https://github.com/luxfhe/v1-sdk.git" }
// Minor URL normalization
```
### 3. js/v2-sdk/package.json
```diff
// Already correctly configured for standalone repo
```
### 4. js/permit/package.json
```diff
- "name": "fhe-permit"
+ "name": "@luxfhe/permit"
- "repository": { "url": "git+https://github.com/luxfheProtocol/fhe.git" }
+ "repository": { "url": "https://github.com/luxfhe/permit.git" }
```
### 5. plugins/hardhat/package.json
```diff
- "name": "fhe-hardhat-plugin"
+ "name": "@luxfhe/hardhat-plugin"
- "repository": "github:luxfheProtocol/fhe-hardhat-plugin"
+ "repository": { "url": "https://github.com/luxfhe/hardhat-plugin.git" }
- "@luxfhe/fhe-contracts": "0.0.13"
+ "@luxfhe/contracts": "^0.5.0"
- "@luxfhe/fhe-mock-contracts": "^0.3.0"
+ "@luxfhe/mocks": "^0.5.0"
```
### 6. proto/decryption-oracle/go.mod
```diff
- module github.com/fhenixprotocol/decryption-oracle-proto
+ module github.com/luxfhe/proto
```
## Import Path Changes
### Solidity Imports
```diff
- import "@fhenixprotocol/contracts/FHE.sol";
+ import "@luxfhe/contracts/FHE.sol";
- import "fhe/contracts/...";
+ import "@luxfhe/contracts/...";
```
### JavaScript/TypeScript Imports
```diff
- import { ... } from "fhe";
+ import { ... } from "@luxfhe/v2-sdk";
- import { ... } from "@fhenixprotocol/v1-sdk";
+ import { ... } from "@luxfhe/v1-sdk";
- import { ... } from "fhe-permit";
+ import { ... } from "@luxfhe/permit";
```
### Go Imports
```diff
- import "github.com/fhenixprotocol/decryption-oracle-proto"
+ import "github.com/luxfhe/proto"
```
## Migration Order (Dependency-Aware)
1. **Phase 1 - Core (no internal deps)**
- contracts
- v1-sdk
- v2-sdk
- permit
- proto
- wasm-sdk
2. **Phase 2 - Dependent packages**
- mocks (depends on contracts)
- hardhat-plugin (depends on contracts, sdk)
- remix-plugin
3. **Phase 3 - Applications**
- examples
- templates
- scaffold-eth
- docs
4. **Phase 4 - Research/Internal**
- research
- ml
- fhe-sdk
- relayer
## Files to Create in Each Repo
Each new repo needs:
- `README.md` - Project-specific documentation
- `LICENSE` - BSD-3-Clause or MIT (match current)
- `.gitignore` - Language-appropriate ignores
- `CHANGELOG.md` - Version history
- `.github/workflows/` - CI/CD pipelines (optional, add later)
## Notes
1. **hardhat-plugin/ vs plugins/hardhat/**: These appear to be duplicates. Merge into single `luxfhe/hardhat-plugin`.
2. **sdk/fhe/**: This is a Turborepo monorepo with multiple packages. Consider whether to flatten or keep as monorepo.
3. **tests/**: Distribute e2e tests to relevant repos rather than keeping separate.
4. **Git History**: Use `git filter-repo` or `git subtree split` to preserve commit history if important.
5. **NPM Publishing**: All `@luxfhe/*` packages should use `publishConfig.access: "public"`.
-152
View File
@@ -1,152 +0,0 @@
# TFHE Makefile
# Production-ready build system for multi-platform SDK
.PHONY: all build test bench clean profile c python wasm install help
# Default target
all: build test
# Build all packages
build:
go build ./...
# Run all tests
test:
go test -v ./...
# Run benchmarks
bench:
go test -bench=. -benchmem ./...
# Run benchmarks with count for statistical significance
bench-count:
go test -bench=. -benchmem -count=5 ./... | tee bench.txt
# Clean build artifacts
clean:
rm -rf c/build python/dist python/build python/*.egg-info
rm -f cpu.prof mem.prof block.prof mutex.prof trace.out
rm -f profile
# Profile targets
profile: profile-build
./profile -cpu=cpu.prof -mem=mem.prof -iterations=100 -op=all
profile-build:
go build -tags profile -o profile ./cmd/profile
profile-cpu: profile-build
./profile -cpu=cpu.prof -iterations=1000 -op=gates
go tool pprof -http=:8080 cpu.prof
profile-mem: profile-build
./profile -mem=mem.prof -iterations=100 -op=keygen
go tool pprof -http=:8080 mem.prof
# C/C++ bindings
c:
cd c && mkdir -p build && cd build && cmake .. && make
c-test: c
cd c/build && ctest --output-on-failure
c-install: c
cd c/build && make install
c-clean:
rm -rf c/build
# Python bindings
python: c
cd python && pip install -e .
python-test: python
cd python && python -m pytest tests/
python-build: c
cd python && pip wheel . -w dist/
python-clean:
rm -rf python/dist python/build python/*.egg-info
# WASM bindings
wasm:
cd ../tfhe-wasm && make wasm
wasm-release:
cd ../tfhe-wasm && make wasm-release
wasm-small:
cd ../tfhe-wasm && make wasm-small
wasm-size:
cd ../tfhe-wasm && make size
# Install development dependencies
deps:
go mod download
go mod tidy
# Format code
fmt:
go fmt ./...
gofmt -s -w .
# Lint code
lint:
golangci-lint run
# Generate code coverage report
coverage:
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
@echo "Coverage report: coverage.html"
# Run security analysis
security:
gosec ./...
# Static analysis
vet:
go vet ./...
# All quality checks
check: fmt vet lint security test
# Help
help:
@echo "TFHE SDK Makefile"
@echo ""
@echo "Build targets:"
@echo " all - Build and test (default)"
@echo " build - Build all packages"
@echo " test - Run all tests"
@echo " bench - Run benchmarks"
@echo " clean - Remove build artifacts"
@echo ""
@echo "Profile targets:"
@echo " profile - Run full profiling suite"
@echo " profile-cpu - CPU profiling with web UI"
@echo " profile-mem - Memory profiling with web UI"
@echo ""
@echo "C/C++ bindings:"
@echo " c - Build C bindings"
@echo " c-test - Run C tests"
@echo " c-install - Install C library"
@echo ""
@echo "Python bindings:"
@echo " python - Install Python bindings (dev)"
@echo " python-test - Run Python tests"
@echo " python-build - Build Python wheel"
@echo ""
@echo "WASM bindings:"
@echo " wasm - Build WASM module"
@echo " wasm-release - Build optimized WASM"
@echo " wasm-small - Build size-optimized WASM"
@echo ""
@echo "Quality checks:"
@echo " fmt - Format code"
@echo " lint - Run linter"
@echo " vet - Run go vet"
@echo " coverage - Generate coverage report"
@echo " check - Run all quality checks"
-233
View File
@@ -1,233 +0,0 @@
# FHE Optimization Guide
## Performance Optimization Strategies
This document describes the optimizations implemented in the Lux FHE library and provides guidance for achieving maximum performance.
## Architecture Overview
```
+-----------------------+
| High-Level API |
| (Boolean/Integer) |
+-----------+-----------+
|
+-----------v-----------+
| Evaluator |
| (Gate Evaluation) |
+-----------+-----------+
|
+-------------------+-------------------+
| |
+-----------v-----------+ +-------------v-------------+
| CPU Backend | | GPU Backend (MLX) |
| (lattice/v6) | | (Metal/CUDA/CPU) |
+-----------+-----------+ +-------------+-------------+
| |
+-----------v-----------+ +-------------v-------------+
| NTT Engine | | Batch Bootstrapping |
| (SIMD-optimized) | | (Parallel PBS) |
+-----------------------+ +---------------------------+
```
## Key Optimizations
### 1. NTT Optimization
The Number Theoretic Transform is the core operation in FHE, used extensively in polynomial multiplication during bootstrapping.
**Cooley-Tukey NTT Algorithm**:
- O(N log N) complexity
- In-place computation with bit-reversal permutation
- Butterfly operations are SIMD-vectorizable
**Barrett Reduction**:
- Avoids expensive division in modular arithmetic
- Precomputes mu = floor(2^64 / Q)
- Reduces multiplication cost by 2-3x
```go
// Barrett reduction for a * b mod Q
func (e *NTTEngine) mulModBarrett(a, b uint64) uint64 {
hi, lo := mul64(a, b)
q := ((hi * e.barrettMu) >> 64) + ((lo * e.barrettMu) >> 32)
r := lo - q*e.Q
// At most 2 subtractions needed for correction
if r >= e.Q { r -= e.Q }
if r >= e.Q { r -= e.Q }
return r
}
```
**Batch NTT**:
- Process multiple polynomials in parallel
- Optimal for GPU where batch size determines efficiency
- CPU version uses goroutine parallelism
### 2. GPU Bootstrapping Pipeline
The GPU engine implements a complete bootstrapping pipeline:
```
Input LWE → Batch NTT → External Products → Blind Rotation → INTT → Key Switch → Output LWE
```
**Key optimizations**:
1. **Structure of Arrays (SoA)**: All data stored for coalesced memory access
```
// Bad: Array of Structures
type LWE struct { a []uint64; b uint64 }
ciphertexts []LWE // Poor memory locality
// Good: Structure of Arrays
type LWEPool struct {
A *gpulib.Array // [batch, n] - contiguous
B *gpulib.Array // [batch] - contiguous
}
```
2. **Fused Kernels**: Combine multiple operations to reduce memory traffic
- External product: decompose → multiply → accumulate in one pass
- Blind rotation: all n external products batched
3. **Precomputed Data**: Twiddle factors and test polynomials computed once at initialization
### 3. Gate-Level Optimizations
**XOR/XNOR Optimization** (matching OpenFHE):
```
// Standard: 2 bootstraps for XOR
result = Bootstrap(a + b, TestPolyPositive) XOR Bootstrap(a + b, TestPolyNegative)
// Optimized: 1 bootstrap with doubling trick
doubled = 2 * (a + b) // Causes (1,1) case to wrap to negative
result = Bootstrap(doubled, TestPolyXOR)
```
**MAJORITY Gate** (single bootstrap):
```
// 3-input MAJORITY with 1 bootstrap
sum = a + b + c
// Threshold at 0 separates:
// 0-1 true inputs (sum < 0) → FALSE
// 2-3 true inputs (sum > 0) → TRUE
result = Bootstrap(sum, TestPolyMAJORITY)
```
**NOT Gate** (free operation):
```
// NOT requires no bootstrap - just negate coefficients
NOT(ct) = -ct // O(N) polynomial negation
```
### 4. Parameter Selection
| Parameter | PN10QP27 | PN11QP54 | Effect |
|-----------|----------|----------|--------|
| N (ring dimension) | 1024 | 2048 | Higher = more security, slower |
| Q (modulus) | 2^27 | 2^54 | Higher = more precision |
| n (LWE dimension) | 512 | 640 | Higher = more security |
| L (decomposition) | 4 | 5 | Higher = less noise, more compute |
| BaseLog | 7 | 10 | Higher = larger gadget, less noise |
**Choosing Parameters**:
- Use **PN10QP27** for most applications (128-bit security, balanced)
- Use **PN11QP54** when you need higher precision or longer circuits
**L (Decomposition Level) Tradeoff**:
```
L = 7 (original): Lower noise, but more computation
L = 4 (optimized): ~1.75x faster, still secure
External product cost = O(L × N × log N)
Reducing L from 7 to 4 gives ~1.75x speedup
```
### 5. Memory Optimization
**Bootstrap Key Size**:
```
BSK size = n × 2 × L × 2 × N × 8 bytes
= 512 × 2 × 4 × 2 × 1024 × 8
= 134 MB per user (with L=4)
```
**GPU Memory Budget** (per 8x H200 config):
- Total: 1.1 TB (141 GB × 8)
- Per GPU: 141 GB
- Users per GPU: ~1000 (with 134 MB BSK each)
- Total users: ~8000
### 6. Parallelization Strategies
**CPU**:
- Batch NTT uses goroutines (16 workers max)
- Gate evaluations can run in parallel with separate evaluators
- No lock contention on read-only bootstrap keys
**GPU**:
- Batch size determines efficiency (optimal: 4096+ for H200)
- Operations grouped by gate type for same test polynomial
- Multi-GPU with NVLink for user distribution
## Benchmarking
Run the full benchmark suite:
```bash
# All benchmarks
go test -bench=. -benchtime=5s ./...
# Specific benchmarks
go test -bench=BenchmarkBootstrap -benchtime=10s
go test -bench=BenchmarkNTT -benchtime=5s
go test -bench=BenchmarkBatch -benchtime=5s
# Memory allocation analysis
go test -bench=BenchmarkMemory -benchmem
# Generate performance report
go test -run=TestPerformanceReport -v
```
## Expected Performance (Apple M1 Max)
| Operation | Time | Notes |
|-----------|------|-------|
| Bootstrap Key Gen | 132 ms | 18x faster than OpenFHE |
| AND/OR/NAND/NOR | ~51 ms | Single bootstrap |
| XOR/XNOR | ~51 ms | Optimized single bootstrap |
| MAJORITY | ~59 ms | Single bootstrap |
| AND3/OR3 | ~117 ms | 2 bootstraps |
| MUX | ~170 ms | 3 bootstraps |
| NOT | 1.2 µs | Free (no bootstrap) |
| NTT (N=1024) | ~30 µs | Per transform |
| Batch NTT (32×) | ~14 µs/poly | Amortized |
## GPU Performance Targets
| Platform | Throughput | Latency |
|----------|------------|---------|
| M1 Max (Metal) | ~60K gates/sec | ~17 µs |
| H100 (CUDA) | ~180K gates/sec | ~5.5 µs |
| H200 (CUDA) | ~250K gates/sec | ~4 µs |
| 8× H200 (NVLink) | ~1.5M gates/sec | ~0.7 µs |
## Best Practices
1. **Batch Operations**: Always batch multiple gate operations together
2. **Reuse Keys**: Generate bootstrap key once, use for many operations
3. **Choose Right Parameters**: PN10QP27 for most use cases
4. **Use NOT Freely**: NOT is essentially free (no bootstrap)
5. **Minimize Circuit Depth**: Fewer sequential bootstraps = faster
6. **Prefer MAJORITY**: Single bootstrap for 3-input majority vote
7. **GPU for Batch**: GPU acceleration shines with 1000+ operations
## Future Optimizations
1. **AVX-512 NTT**: Assembly-optimized NTT for x86-64
2. **NEON NTT**: Assembly-optimized NTT for ARM64
3. **Metal Shaders**: Custom Metal kernels for NTT butterfly
4. **CUDA Kernels**: Custom CUDA kernels for H100/H200
5. **Circuit Compiler**: Automatic circuit optimization and batching
-221
View File
@@ -1,221 +0,0 @@
# Lux FHE
**Fully Homomorphic Encryption for the Lux Network** — Pure Go with optional C++/CUDA acceleration.
[![Go Reference](https://pkg.go.dev/badge/github.com/luxfi/fhe.svg)](https://pkg.go.dev/github.com/luxfi/fhe)
[![CI](https://github.com/luxfi/fhe/actions/workflows/ci.yml/badge.svg)](https://github.com/luxfi/fhe/actions/workflows/ci.yml)
[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE)
## Overview
Lux FHE is a production-ready implementation of Fully Homomorphic Encryption (FHE) that enables computation on encrypted data without decryption. Ideal for privacy-preserving blockchain applications, confidential smart contracts, and secure multi-party computation.
## Implementations
| Mode | Build Flag | Description |
|------|------------|-------------|
| **Pure Go** | `CGO_ENABLED=0` | Zero dependencies, compiles anywhere Go runs |
| **C++ Optimized** | `CGO_ENABLED=1` | High-performance [C++ backend](https://github.com/luxcpp/fhe) |
| **GPU Accelerated** | `CGO_ENABLED=1` + GPU | Metal (macOS), CUDA (Linux/Windows) |
> **Enterprise:** Multi-GPU, cloud deployments, and advanced optimizations available through enterprise licensing.
### Pure Go Mode
- **Zero external dependencies** — compiles anywhere Go runs
- **Cross-platform** — Linux, macOS, Windows, ARM64
- **Deterministic builds** — critical for blockchain consensus
- **Easy deployment** — single static binary
### C++/GPU Mode
For maximum performance, build with CGO enabled to use our optimized [C++ implementation](https://github.com/luxcpp/fhe):
```bash
# macOS (Metal GPU automatic)
CGO_ENABLED=1 go build ./...
# Linux/Windows with CUDA
CGO_ENABLED=1 go build -tags cuda ./...
# Linux/Windows CPU-only
CGO_ENABLED=1 go build ./...
```
See [luxcpp/fhe](https://github.com/luxcpp/fhe) for C++/CUDA/MLX implementation details.
## Blockchain Optimized
- **Public key encryption** — users encrypt without secret key access
- **Deterministic RNG** — blockchain-compatible random numbers
- **Full serialization** — keys and ciphertexts
- **FheUint160** — native Ethereum address support
- **FheUint256** — native EVM word size support
## Performance (Apple M1 Max)
| Operation | Pure Go | C++ (CGO) | GPU |
|-----------|---------|-----------|-----|
| Bootstrap Key Gen | 132 ms | 68 ms | 12 ms |
| Boolean Gate (AND) | 51 ms | 28 ms | 3 ms |
| 8-bit Addition | 5.0 s | 2.1 s | 180 ms |
See [BENCHMARKS.md](BENCHMARKS.md) for complete performance data.
## Installation
```bash
go get github.com/luxfi/fhe
```
## Quick Start
```go
package main
import (
"fmt"
fhe "github.com/luxfi/fhe"
)
func main() {
// Setup
params, _ := fhe.NewParametersFromLiteral(fhe.PN10QP27)
kg := fhe.NewKeyGenerator(params)
sk, pk := kg.GenKeyPair()
bsk := kg.GenBootstrapKey(sk)
// Encrypt with public key (user side - no secret key needed!)
pubEnc := fhe.NewBitwisePublicEncryptor(params, pk)
ctA, _ := pubEnc.EncryptUint64(5, fhe.FheUint8)
ctB, _ := pubEnc.EncryptUint64(3, fhe.FheUint8)
// Compute on encrypted data (server/blockchain side)
eval := fhe.NewBitwiseEvaluator(params, bsk, sk)
ctSum, _ := eval.Add(ctA, ctB)
// Decrypt result
dec := fhe.NewBitwiseDecryptor(params, sk)
result := dec.DecryptUint64(ctSum)
fmt.Println("5 + 3 =", result) // Output: 5 + 3 = 8
}
```
## Supported Types
| Type | Bits | Use Case |
|------|------|----------|
| FheBool | 1 | Boolean flags, comparisons |
| FheUint4 | 4 | Small counters, nibbles |
| FheUint8 | 8 | Bytes, small values |
| FheUint16 | 16 | Short integers |
| FheUint32 | 32 | Standard integers |
| FheUint64 | 64 | Large integers |
| FheUint128 | 128 | UUIDs, large values |
| FheUint160 | 160 | **Ethereum addresses** |
| FheUint256 | 256 | **EVM word size** |
## Operations
**Arithmetic**: `Add`, `Sub`, `ScalarAdd`, `Neg`
**Comparison**: `Eq`, `Lt`, `Le`, `Gt`, `Ge`, `Min`, `Max`
**Bitwise**: `And`, `Or`, `Xor`, `Not`, `Shl`, `Shr`
**Selection**: `Select` (encrypted if-then-else), `CastTo`
## Architecture
```
github.com/luxfi/fhe/
├── fhe.go # Parameters, key types, key generation
├── encryptor.go # Boolean encryption (secret key)
├── decryptor.go # Boolean decryption
├── evaluator.go # Boolean gates (AND, OR, XOR, NOT, MUX)
├── bitwise_integers.go # Integer operations + public key encryption
├── integers.go # FheUintType definitions
├── integer_ops.go # Comparison, bitwise operations
├── serialization.go # Key/ciphertext serialization
├── random.go # FHE random number generation
├── server/ # HTTP server for benchmarking
└── gpu/ # GPU acceleration stubs
```
## Dependencies
- [`github.com/luxfi/lattice/v6`](https://github.com/luxfi/lattice) — Lattice cryptography primitives
## Running Tests
```bash
# Pure Go tests (all core packages)
CGO_ENABLED=0 go test -v ./...
# With C++ backend + GPU (requires luxcpp/fhe)
CGO_ENABLED=1 go test -v ./...
# Benchmarks
go test -bench=. -benchmem -run=^$
```
## Package Structure
| Package | CGO Required | Description |
|---------|--------------|-------------|
| `github.com/luxfi/fhe` | No | Core FHE library (pure Go) |
| `github.com/luxfi/fhe/cgo` | Yes | C++ bridge to OpenFHE |
| `github.com/luxfi/fhe/gpu` | Yes | GPU acceleration (MLX) |
| `github.com/luxfi/fhe/server` | Yes | HTTP server with GPU support |
| `github.com/luxfi/fhe/cmd/fhe-server` | Yes | Standalone FHE server |
| `github.com/luxfi/fhe/cmd/fhe-gateway` | No | Pure Go gateway |
| `github.com/luxfi/fhe/cmd/fhe-worker` | No | Pure Go worker |
## HTTP Benchmark Server
GPU-accelerated server (requires CGO):
```bash
# Build and run server
CGO_ENABLED=1 go run ./cmd/fhe-server -addr :8448 -gpu
# C++ server (see luxcpp/fhe)
./fhe-server --port 8081
```
## License
**BSD-3-Clause**
Lux FHE is open source software. Patent rights for novel optimizations are reserved by Lux Partners Limited.
- **Lux Network**: Free to use on Lux mainnet and testnets
- **Research/Academic**: Free for non-commercial use
- **Commercial**: Contact licensing@lux.partners
See [LICENSE](LICENSE) for full terms.
## Implementation
Original implementation based on published academic research:
- Built on [`github.com/luxfi/lattice`](https://github.com/luxfi/lattice) (our cryptographic primitives)
- Implements peer-reviewed algorithms from academic publications
- Contains novel optimizations developed independently
**Academic References:**
- Chillotti et al. "FHE: Fast Fully Homomorphic Encryption Over the Torus" (Journal of Cryptology, 2020)
- Ducas & Micciancio "FHEW: Bootstrapping Homomorphic Encryption in Less Than a Second" (EUROCRYPT 2015)
## Related Projects
- [luxcpp/fhe](https://github.com/luxcpp/fhe) — C++/CUDA/MLX implementation
- [luxfi/lattice](https://github.com/luxfi/lattice) — Lattice cryptography library
- [luxfi/standard](https://github.com/luxfi/standard) — fhEVM smart contracts
## Contributing
Contributions welcome! Please ensure tests pass before submitting PRs:
```bash
CGO_ENABLED=0 go test -v ./...
go vet ./...
```
-1508
View File
File diff suppressed because it is too large Load Diff
-531
View File
@@ -1,531 +0,0 @@
// Copyright (c) 2024 The Lux Authors
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.
package fhe
import (
"testing"
)
// Comprehensive benchmarks for pure Go (lattice) backend
// These mirror the CGO benchmarks for comparison
var (
benchParams Parameters
benchKGen *KeyGenerator
benchSK *SecretKey
benchPK *PublicKey
benchBSK *BootstrapKey
benchEnc *Encryptor
benchDec *Decryptor
benchEval *Evaluator
benchBitEnc *BitwiseEncryptor
benchBitDec *BitwiseDecryptor
benchBitEval *BitwiseEvaluator
)
func setupBenchmark(b *testing.B) {
if benchKGen != nil {
return
}
var err error
benchParams, err = NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatalf("failed to create params: %v", err)
}
benchKGen = NewKeyGenerator(benchParams)
benchSK = benchKGen.GenSecretKey()
benchPK = benchKGen.GenPublicKey(benchSK)
benchBSK = benchKGen.GenBootstrapKey(benchSK)
benchEnc = NewEncryptor(benchParams, benchSK)
benchDec = NewDecryptor(benchParams, benchSK)
benchEval = NewEvaluator(benchParams, benchBSK)
benchBitEnc = NewBitwiseEncryptor(benchParams, benchSK)
benchBitDec = NewBitwiseDecryptor(benchParams, benchSK)
benchBitEval = NewBitwiseEvaluator(benchParams, benchBSK, benchSK)
}
// ============================================================================
// Key Generation Benchmarks
// ============================================================================
func BenchmarkLatticeKeyGen(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kgen := NewKeyGenerator(params)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = kgen.GenSecretKey()
}
}
func BenchmarkLatticePublicKeyGen(b *testing.B) {
setupBenchmark(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchKGen.GenPublicKey(benchSK)
}
}
func BenchmarkLatticeBootstrapKeyGen(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kgen := NewKeyGenerator(params)
sk := kgen.GenSecretKey()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = kgen.GenBootstrapKey(sk)
}
}
// ============================================================================
// Boolean Encryption/Decryption Benchmarks
// ============================================================================
func BenchmarkLatticeEncryptBit(b *testing.B) {
setupBenchmark(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchEnc.Encrypt(true)
}
}
func BenchmarkLatticeDecryptBit(b *testing.B) {
setupBenchmark(b)
ct := benchEnc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchDec.Decrypt(ct)
}
}
// ============================================================================
// Boolean Gate Benchmarks
// ============================================================================
func BenchmarkLatticeAND(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.AND(ct1, ct2)
}
}
func BenchmarkLatticeOR(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.OR(ct1, ct2)
}
}
func BenchmarkLatticeXOR(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.XOR(ct1, ct2)
}
}
func BenchmarkLatticeNOT(b *testing.B) {
setupBenchmark(b)
ct := benchEnc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchEval.NOT(ct)
}
}
func BenchmarkLatticeNAND(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.NAND(ct1, ct2)
}
}
func BenchmarkLatticeNOR(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.NOR(ct1, ct2)
}
}
func BenchmarkLatticeXNOR(b *testing.B) {
setupBenchmark(b)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.XNOR(ct1, ct2)
}
}
func BenchmarkLatticeMUX(b *testing.B) {
setupBenchmark(b)
sel := benchEnc.Encrypt(true)
ct1 := benchEnc.Encrypt(true)
ct2 := benchEnc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchEval.MUX(sel, ct1, ct2)
}
}
// ============================================================================
// Integer Encryption/Decryption Benchmarks
// ============================================================================
func BenchmarkLatticeEncryptInt8(b *testing.B) {
setupBenchmark(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEnc.EncryptUint64(42, FheUint8)
}
}
func BenchmarkLatticeEncryptInt16(b *testing.B) {
setupBenchmark(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEnc.EncryptUint64(12345, FheUint16)
}
}
func BenchmarkLatticeEncryptInt32(b *testing.B) {
setupBenchmark(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEnc.EncryptUint64(123456789, FheUint32)
}
}
func BenchmarkLatticeDecryptInt8(b *testing.B) {
setupBenchmark(b)
ct := benchBitEnc.EncryptUint64(42, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitDec.DecryptUint64(ct)
}
}
func BenchmarkLatticeDecryptInt16(b *testing.B) {
setupBenchmark(b)
ct := benchBitEnc.EncryptUint64(12345, FheUint16)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitDec.DecryptUint64(ct)
}
}
// ============================================================================
// Integer Arithmetic Benchmarks
// ============================================================================
func BenchmarkLatticeAdd8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Add(a, c)
}
}
func BenchmarkLatticeAdd16(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(1000, FheUint16)
c := benchBitEnc.EncryptUint64(2000, FheUint16)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Add(a, c)
}
}
func BenchmarkLatticeSub8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(50, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Sub(a, c)
}
}
func BenchmarkLatticeScalarAdd8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(42, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.ScalarAdd(a, 10)
}
}
// ============================================================================
// Comparison Benchmarks
// ============================================================================
func BenchmarkLatticeEq8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(42, FheUint8)
c := benchBitEnc.EncryptUint64(42, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Eq(a, c)
}
}
func BenchmarkLatticeLt8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Lt(a, c)
}
}
func BenchmarkLatticeLe8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Le(a, c)
}
}
func BenchmarkLatticeGt8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(20, FheUint8)
c := benchBitEnc.EncryptUint64(10, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Gt(a, c)
}
}
func BenchmarkLatticeMin8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Min(a, c)
}
}
func BenchmarkLatticeMax8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Max(a, c)
}
}
// ============================================================================
// Bitwise Operation Benchmarks
// ============================================================================
func BenchmarkLatticeBitwiseAnd8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0xFF, FheUint8)
c := benchBitEnc.EncryptUint64(0x0F, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.And(a, c)
}
}
func BenchmarkLatticeBitwiseOr8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0xF0, FheUint8)
c := benchBitEnc.EncryptUint64(0x0F, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Or(a, c)
}
}
func BenchmarkLatticeBitwiseXor8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0xFF, FheUint8)
c := benchBitEnc.EncryptUint64(0x55, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Xor(a, c)
}
}
func BenchmarkLatticeBitwiseNot8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0xFF, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEval.Not(a)
}
}
func BenchmarkLatticeShl8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0x0F, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEval.Shl(a, 2)
}
}
func BenchmarkLatticeShr8(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(0xF0, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEval.Shr(a, 2)
}
}
// ============================================================================
// Control Flow Benchmarks
// ============================================================================
func BenchmarkLatticeSelect8(b *testing.B) {
setupBenchmark(b)
cond := benchEnc.Encrypt(true)
a := benchBitEnc.EncryptUint64(10, FheUint8)
c := benchBitEnc.EncryptUint64(20, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = benchBitEval.Select(cond, a, c)
}
}
func BenchmarkLatticeCastTo16(b *testing.B) {
setupBenchmark(b)
a := benchBitEnc.EncryptUint64(42, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = benchBitEval.CastTo(a, FheUint16)
}
}
// ============================================================================
// Public Key Encryption Benchmarks
// ============================================================================
func BenchmarkLatticePublicEncrypt8(b *testing.B) {
setupBenchmark(b)
pubEnc := NewBitwisePublicEncryptor(benchParams, benchPK)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = pubEnc.EncryptUint64(42, FheUint8)
}
}
func BenchmarkLatticePublicEncrypt16(b *testing.B) {
setupBenchmark(b)
pubEnc := NewBitwisePublicEncryptor(benchParams, benchPK)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = pubEnc.EncryptUint64(12345, FheUint16)
}
}
// ============================================================================
// Serialization Benchmarks
// ============================================================================
func BenchmarkLatticeSerializeCiphertext(b *testing.B) {
setupBenchmark(b)
ct := benchEnc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = ct.MarshalBinary()
}
}
func BenchmarkLatticeDeserializeCiphertext(b *testing.B) {
setupBenchmark(b)
ct := benchEnc.Encrypt(true)
data, _ := ct.MarshalBinary()
b.ResetTimer()
for i := 0; i < b.N; i++ {
var ct2 Ciphertext
_ = ct2.UnmarshalBinary(data)
}
}
func BenchmarkLatticeSerializeInteger8(b *testing.B) {
setupBenchmark(b)
ct := benchBitEnc.EncryptUint64(42, FheUint8)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = ct.MarshalBinary()
}
}
func BenchmarkLatticeSerializeInteger16(b *testing.B) {
setupBenchmark(b)
ct := benchBitEnc.EncryptUint64(12345, FheUint16)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = ct.MarshalBinary()
}
}
// ============================================================================
// RNG Benchmarks
// ============================================================================
func BenchmarkLatticeRNGRandomUint8(b *testing.B) {
setupBenchmark(b)
rng := NewFheRNG(benchParams, benchSK, []byte("benchmark-seed"))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = rng.RandomUint(FheUint8)
}
}
func BenchmarkLatticeRNGRandomUint16(b *testing.B) {
setupBenchmark(b)
rng := NewFheRNG(benchParams, benchSK, []byte("benchmark-seed"))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = rng.RandomUint(FheUint16)
}
}
// ============================================================================
// Memory Allocation Benchmarks
// ============================================================================
func BenchmarkLatticeAllocCiphertext(b *testing.B) {
setupBenchmark(b)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ct := benchEnc.Encrypt(true)
_ = ct
}
}
func BenchmarkLatticeAllocInteger8(b *testing.B) {
setupBenchmark(b)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
ct := benchBitEnc.EncryptUint64(42, FheUint8)
_ = ct
}
}
-191
View File
@@ -1,191 +0,0 @@
// Benchmark tests with OpenFHE-compatible parameters
// These benchmarks use parameters that closely match OpenFHE's STD128_LMKCDEY
// for fair comparison between Go and C++ implementations.
package fhe
import (
"testing"
)
// BenchmarkSTD128_AND benchmarks AND gate with STD128-compatible parameters
func BenchmarkSTD128_AND(b *testing.B) {
params, err := NewParametersFromLiteral(PN9QP28_STD128)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.AND(ct1, ct2)
}
}
// BenchmarkSTD128_OR benchmarks OR gate with STD128-compatible parameters
func BenchmarkSTD128_OR(b *testing.B) {
params, err := NewParametersFromLiteral(PN9QP28_STD128)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.OR(ct1, ct2)
}
}
// BenchmarkSTD128_XOR benchmarks XOR gate with STD128-compatible parameters
func BenchmarkSTD128_XOR(b *testing.B) {
params, err := NewParametersFromLiteral(PN9QP28_STD128)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.XOR(ct1, ct2)
}
}
// BenchmarkSTD128_NOT benchmarks NOT gate with STD128-compatible parameters
func BenchmarkSTD128_NOT(b *testing.B) {
params, err := NewParametersFromLiteral(PN9QP28_STD128)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct := enc.EncryptBit(1)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = eval.NOT(ct)
}
}
// BenchmarkSTD128_NAND benchmarks NAND gate (includes bootstrap) with STD128-compatible parameters
func BenchmarkSTD128_NAND(b *testing.B) {
params, err := NewParametersFromLiteral(PN9QP28_STD128)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.NAND(ct1, ct2)
}
}
// BenchmarkPN10QP27_AND benchmarks AND gate with original PN10QP27 parameters for comparison
func BenchmarkPN10QP27_AND(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.AND(ct1, ct2)
}
}
// BenchmarkPN10QP27_OR benchmarks OR gate with original PN10QP27 parameters for comparison
func BenchmarkPN10QP27_OR(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.OR(ct1, ct2)
}
}
// BenchmarkPN10QP27_XOR benchmarks XOR gate with original PN10QP27 parameters for comparison
func BenchmarkPN10QP27_XOR(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.EncryptBit(1)
ct2 := enc.EncryptBit(0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.XOR(ct1, ct2)
}
}
-534
View File
@@ -1,534 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
package fhe
import (
"fmt"
"math/rand"
"sync"
"testing"
"time"
)
// BenchmarkBootstrapBaseline measures baseline bootstrap performance
func BenchmarkBootstrapBaseline(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(true)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.AND(ct1, ct2)
}
}
// BenchmarkBootstrapParallelGates measures parallel gate execution
func BenchmarkBootstrapParallelGates(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
numGates := 8
type gateInput struct {
eval *Evaluator
ct1 *Ciphertext
ct2 *Ciphertext
}
inputs := make([]gateInput, numGates)
for i := 0; i < numGates; i++ {
inputs[i] = gateInput{
eval: NewEvaluator(params, bsk),
ct1: enc.Encrypt(true),
ct2: enc.Encrypt(false),
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
var wg sync.WaitGroup
for j := 0; j < numGates; j++ {
wg.Add(1)
go func(idx int) {
defer wg.Done()
_, _ = inputs[idx].eval.AND(inputs[idx].ct1, inputs[idx].ct2)
}(j)
}
wg.Wait()
}
}
// BenchmarkNTTComparison compares NTT implementations
func BenchmarkNTTComparison(b *testing.B) {
// Use NTT-friendly primes: Q = k*2N + 1 for some k
// These primes support the required primitive roots of unity
testCases := []struct {
N int
Q uint64
}{
{512, 12289}, // 12289 = 12*1024 + 1
{1024, 12289}, // 12289 = 6*2048 + 1
{2048, 12289}, // 12289 = 3*4096 + 1
{4096, 40961}, // 40961 = 5*8192 + 1
}
for _, tc := range testCases {
b.Run(fmt.Sprintf("N=%d", tc.N), func(b *testing.B) {
engine, err := NewNTTEngine(uint32(tc.N), tc.Q)
if err != nil {
b.Skipf("NTT engine init failed for N=%d, Q=%d: %v", tc.N, tc.Q, err)
return
}
coeffs := make([]uint64, tc.N)
for i := range coeffs {
coeffs[i] = uint64(rand.Int63n(int64(tc.Q)))
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
engine.NTTInPlace(coeffs)
}
})
}
}
// BenchmarkBatchNTT measures batch NTT performance scaling
func BenchmarkBatchNTT(b *testing.B) {
N := 1024
Q := uint64(12289) // NTT-friendly prime
engine, err := NewNTTEngine(uint32(N), Q)
if err != nil {
b.Skipf("NTT engine init failed: %v", err)
return
}
batchSizes := []int{1, 4, 16, 64, 256}
for _, batchSize := range batchSizes {
b.Run(fmt.Sprintf("batch=%d", batchSize), func(b *testing.B) {
polys := make([][]uint64, batchSize)
for i := range polys {
polys[i] = make([]uint64, N)
for j := range polys[i] {
polys[i][j] = uint64(rand.Int63n(int64(Q)))
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
engine.NTTBatch(polys)
}
})
}
}
// BenchmarkPolyMulScaling measures polynomial multiplication scaling
func BenchmarkPolyMulScaling(b *testing.B) {
N := 1024
Q := uint64(12289) // NTT-friendly prime
engine, err := NewNTTEngine(uint32(N), Q)
if err != nil {
b.Skipf("NTT engine init failed: %v", err)
return
}
a := make([]uint64, N)
bb := make([]uint64, N)
result := make([]uint64, N)
for i := range a {
a[i] = uint64(rand.Int63n(int64(Q)))
bb[i] = uint64(rand.Int63n(int64(Q)))
}
engine.NTTInPlace(a)
engine.NTTInPlace(bb)
b.Run("PolyMul", func(b *testing.B) {
for i := 0; i < b.N; i++ {
engine.PolyMulNTT(a, bb, result)
}
})
b.Run("PolyMulAccum", func(b *testing.B) {
for i := 0; i < b.N; i++ {
engine.PolyMulNTTAccum(a, bb, result)
}
})
}
// BenchmarkModularOps measures modular arithmetic performance
func BenchmarkModularOps(b *testing.B) {
engine, err := NewNTTEngine(1024, 12289) // NTT-friendly prime
if err != nil {
b.Skipf("NTT engine init failed: %v", err)
return
}
a := uint64(rand.Int63n(int64(engine.Q)))
bb := uint64(rand.Int63n(int64(engine.Q)))
b.Run("MulMod_Standard", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = engine.mulMod(a, bb)
}
})
b.Run("MulMod_Barrett", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = engine.mulModBarrett(a, bb)
}
})
b.Run("AddMod", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = engine.addMod(a, bb)
}
})
b.Run("SubMod", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = engine.subMod(a, bb)
}
})
}
// BenchmarkExternalProduct measures external product performance
func BenchmarkExternalProduct(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct := enc.Encrypt(true)
// Measure a full bootstrap (which includes external products)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.bootstrap(ct, eval.bsk.TestPolyAND)
}
}
// BenchmarkKeyGenerationOptimized measures key generation performance
func BenchmarkKeyGenerationOptimized(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
b.Run("SecretKey", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = kg.GenSecretKey()
}
})
sk := kg.GenSecretKey()
b.Run("PublicKey", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = kg.GenPublicKey(sk)
}
})
b.Run("BootstrapKey", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = kg.GenBootstrapKey(sk)
}
})
}
// BenchmarkEncryptionOptimized measures encryption performance
func BenchmarkEncryptionOptimized(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
enc := NewEncryptor(params, sk)
b.Run("Bit", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = enc.Encrypt(true)
}
})
b.Run("Byte", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = enc.EncryptByte(0xAB)
}
})
b.Run("Uint32", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = enc.EncryptUint32(0xDEADBEEF)
}
})
}
// BenchmarkDecryptionOptimized measures decryption performance
func BenchmarkDecryptionOptimized(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
enc := NewEncryptor(params, sk)
dec := NewDecryptor(params, sk)
ctBit := enc.Encrypt(true)
ctByte := enc.EncryptByte(0xAB)
ctUint32 := enc.EncryptUint32(0xDEADBEEF)
b.Run("Bit", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = dec.DecryptBit(ctBit)
}
})
b.Run("Byte", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = dec.DecryptByte(ctByte)
}
})
b.Run("Uint32", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = dec.DecryptUint32(ctUint32)
}
})
}
// BenchmarkAllGates measures all boolean gate performance
func BenchmarkAllGates(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
ct3 := enc.Encrypt(true)
gates := []struct {
name string
fn func() (*Ciphertext, error)
}{
{"NOT", func() (*Ciphertext, error) { return eval.NOT(ct1), nil }},
{"AND", func() (*Ciphertext, error) { return eval.AND(ct1, ct2) }},
{"OR", func() (*Ciphertext, error) { return eval.OR(ct1, ct2) }},
{"XOR", func() (*Ciphertext, error) { return eval.XOR(ct1, ct2) }},
{"NAND", func() (*Ciphertext, error) { return eval.NAND(ct1, ct2) }},
{"NOR", func() (*Ciphertext, error) { return eval.NOR(ct1, ct2) }},
{"XNOR", func() (*Ciphertext, error) { return eval.XNOR(ct1, ct2) }},
{"MUX", func() (*Ciphertext, error) { return eval.MUX(ct1, ct2, ct3) }},
{"AND3", func() (*Ciphertext, error) { return eval.AND3(ct1, ct2, ct3) }},
{"OR3", func() (*Ciphertext, error) { return eval.OR3(ct1, ct2, ct3) }},
{"MAJORITY", func() (*Ciphertext, error) { return eval.MAJORITY(ct1, ct2, ct3) }},
}
for _, g := range gates {
b.Run(g.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = g.fn()
}
})
}
}
// BenchmarkThroughputOptimized measures sustained throughput
func BenchmarkThroughputOptimized(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
numWorkers := 4
opsPerWorker := 100
b.Run(fmt.Sprintf("Workers=%d", numWorkers), func(b *testing.B) {
for iter := 0; iter < b.N; iter++ {
var wg sync.WaitGroup
start := time.Now()
for w := 0; w < numWorkers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
eval := NewEvaluator(params, bsk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
for i := 0; i < opsPerWorker; i++ {
_, _ = eval.AND(ct1, ct2)
}
}()
}
wg.Wait()
elapsed := time.Since(start)
totalOps := numWorkers * opsPerWorker
opsPerSec := float64(totalOps) / elapsed.Seconds()
b.ReportMetric(opsPerSec, "ops/s")
}
})
}
// BenchmarkMemoryAllocation measures memory allocation patterns
func BenchmarkMemoryAllocation(b *testing.B) {
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.AND(ct1, ct2)
}
}
// BenchmarkParameterSets compares different parameter sets
func BenchmarkParameterSets(b *testing.B) {
paramSets := []struct {
name string
literal ParametersLiteral
}{
{"PN10QP27", PN10QP27},
{"PN11QP54", PN11QP54},
}
for _, ps := range paramSets {
b.Run(ps.name, func(b *testing.B) {
params, err := NewParametersFromLiteral(ps.literal)
if err != nil {
b.Fatalf("failed to create params: %v", err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bsk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = eval.AND(ct1, ct2)
}
})
}
}
// TestPerformanceReport generates a performance summary
func TestPerformanceReport(t *testing.T) {
if testing.Short() {
t.Skip("skipping performance report in short mode")
}
params, _ := NewParametersFromLiteral(PN10QP27)
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
_ = kg.GenPublicKey(sk)
bsk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
dec := NewDecryptor(params, sk)
eval := NewEvaluator(params, bsk)
// Measure key generation
start := time.Now()
for i := 0; i < 10; i++ {
_ = kg.GenBootstrapKey(sk)
}
bskTime := time.Since(start) / 10
// Measure encryption
start = time.Now()
for i := 0; i < 1000; i++ {
_ = enc.Encrypt(true)
}
encTime := time.Since(start) / 1000
// Measure decryption
ct := enc.Encrypt(true)
start = time.Now()
for i := 0; i < 1000; i++ {
_ = dec.Decrypt(ct)
}
decTime := time.Since(start) / 1000
// Measure gates
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
ct3 := enc.Encrypt(true)
gateResults := make(map[string]time.Duration)
numIter := 10
start = time.Now()
for i := 0; i < numIter; i++ {
_, _ = eval.AND(ct1, ct2)
}
gateResults["AND"] = time.Since(start) / time.Duration(numIter)
start = time.Now()
for i := 0; i < numIter; i++ {
_, _ = eval.OR(ct1, ct2)
}
gateResults["OR"] = time.Since(start) / time.Duration(numIter)
start = time.Now()
for i := 0; i < numIter; i++ {
_, _ = eval.XOR(ct1, ct2)
}
gateResults["XOR"] = time.Since(start) / time.Duration(numIter)
start = time.Now()
for i := 0; i < numIter; i++ {
_, _ = eval.MAJORITY(ct1, ct2, ct3)
}
gateResults["MAJORITY"] = time.Since(start) / time.Duration(numIter)
// Print report
fmt.Println("\n========== FHE Performance Report ==========")
fmt.Printf("Parameters: PN10QP27 (N=%d, Q=%d)\n", params.N(), params.QLWE())
fmt.Println()
fmt.Println("Key Generation:")
fmt.Printf(" Bootstrap Key: %v\n", bskTime)
fmt.Println()
fmt.Println("Encryption/Decryption:")
fmt.Printf(" Encrypt Bit: %v\n", encTime)
fmt.Printf(" Decrypt Bit: %v\n", decTime)
fmt.Println()
fmt.Println("Boolean Gates:")
for gate, dur := range gateResults {
gatesPerSec := float64(time.Second) / float64(dur)
fmt.Printf(" %s: %v (%.1f gates/sec)\n", gate, dur, gatesPerSec)
}
fmt.Println("================================================")
}
-411
View File
@@ -1,411 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
package fhe
import (
"fmt"
"testing"
)
// BenchmarkParameters benchmarks parameter set initialization
func BenchmarkParameters(b *testing.B) {
b.Run("PN10QP27", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("PN11QP54", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, err := NewParametersFromLiteral(PN11QP54)
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkKeyGeneration benchmarks key generation
func BenchmarkKeyGeneration(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
b.Run("SecretKey", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
kg.GenSecretKey()
}
})
sk := kg.GenSecretKey()
b.Run("PublicKey", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
kg.GenPublicKey(sk)
}
})
b.Run("BootstrapKey", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
kg.GenBootstrapKey(sk)
}
})
}
// BenchmarkEncryption benchmarks encryption operations
func BenchmarkEncryption(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
enc := NewEncryptor(params, sk)
b.Run("Bit", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
enc.Encrypt(true)
}
})
b.Run("Byte", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
enc.EncryptByte(0x42)
}
})
}
// BenchmarkDecryption benchmarks decryption operations
func BenchmarkDecryption(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
enc := NewEncryptor(params, sk)
dec := NewDecryptor(params, sk)
ctBit := enc.Encrypt(true)
ctByte := enc.EncryptByte(0x42)
b.Run("Bit", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
dec.Decrypt(ctBit)
}
})
b.Run("Byte", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
dec.DecryptByte(ctByte)
}
})
}
// BenchmarkGates benchmarks boolean gate operations
func BenchmarkGates(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
// Basic gates
gates := []struct {
name string
fn func() (*Ciphertext, error)
}{
{"AND", func() (*Ciphertext, error) { return eval.AND(ct1, ct2) }},
{"OR", func() (*Ciphertext, error) { return eval.OR(ct1, ct2) }},
{"XOR", func() (*Ciphertext, error) { return eval.XOR(ct1, ct2) }},
{"NAND", func() (*Ciphertext, error) { return eval.NAND(ct1, ct2) }},
{"NOR", func() (*Ciphertext, error) { return eval.NOR(ct1, ct2) }},
{"XNOR", func() (*Ciphertext, error) { return eval.XNOR(ct1, ct2) }},
}
for _, gate := range gates {
b.Run(gate.name, func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := gate.fn()
if err != nil {
b.Fatal(err)
}
}
})
}
// NOT is special (no bootstrap)
b.Run("NOT", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
eval.NOT(ct1)
}
})
// MUX
ct3 := enc.Encrypt(true)
b.Run("MUX", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := eval.MUX(ct1, ct2, ct3)
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkMultiInputGates benchmarks multi-input gates
func BenchmarkMultiInputGates(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
ct3 := enc.Encrypt(true)
b.Run("AND3", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := eval.AND3(ct1, ct2, ct3)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("OR3", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := eval.OR3(ct1, ct2, ct3)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("MAJORITY", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := eval.MAJORITY(ct1, ct2, ct3)
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkSerialization benchmarks key and ciphertext serialization
func BenchmarkSerialization(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
enc := NewEncryptor(params, sk)
ct := enc.Encrypt(true)
b.Run("SecretKey/Marshal", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := sk.MarshalBinary()
if err != nil {
b.Fatal(err)
}
}
})
skData, _ := sk.MarshalBinary()
b.Run("SecretKey/Unmarshal", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
newSK := new(SecretKey)
err := newSK.UnmarshalBinary(skData)
if err != nil {
b.Fatal(err)
}
}
})
b.Run("Ciphertext/Marshal", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := ct.MarshalBinary()
if err != nil {
b.Fatal(err)
}
}
})
ctData, _ := ct.MarshalBinary()
b.Run("Ciphertext/Unmarshal", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
newCT := new(Ciphertext)
err := newCT.UnmarshalBinary(ctData)
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkCircuit benchmarks a simple circuit (half adder)
func BenchmarkCircuit(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bk)
a := enc.Encrypt(true)
cIn := enc.Encrypt(false)
// Half adder: sum = a XOR b, carry = a AND b
b.Run("HalfAdder", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := eval.XOR(a, cIn)
if err != nil {
b.Fatal(err)
}
_, err = eval.AND(a, cIn)
if err != nil {
b.Fatal(err)
}
}
})
// Full adder: sum = a XOR b XOR cin, cout = (a AND b) OR (cin AND (a XOR b))
c := enc.Encrypt(true)
b.Run("FullAdder", func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
axorb, err := eval.XOR(a, cIn)
if err != nil {
b.Fatal(err)
}
_, err = eval.XOR(axorb, c)
if err != nil {
b.Fatal(err)
}
aandb, err := eval.AND(a, cIn)
if err != nil {
b.Fatal(err)
}
candaxorb, err := eval.AND(c, axorb)
if err != nil {
b.Fatal(err)
}
_, err = eval.OR(aandb, candaxorb)
if err != nil {
b.Fatal(err)
}
}
})
}
// BenchmarkThroughput measures operations per second
func BenchmarkThroughput(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := NewEncryptor(params, sk)
eval := NewEvaluator(params, bk)
// Prepare many ciphertexts
const n = 100
cts := make([]*Ciphertext, n)
for i := 0; i < n; i++ {
cts[i] = enc.Encrypt(i%2 == 0)
}
b.Run(fmt.Sprintf("AND_Chain_%d", n), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := cts[0]
for j := 1; j < n; j++ {
var err error
result, err = eval.AND(result, cts[j])
if err != nil {
b.Fatal(err)
}
}
}
})
b.Run(fmt.Sprintf("XOR_Chain_%d", n), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
result := cts[0]
for j := 1; j < n; j++ {
var err error
result, err = eval.XOR(result, cts[j])
if err != nil {
b.Fatal(err)
}
}
}
})
}
// BenchmarkMemory reports memory usage for key structures
func BenchmarkMemory(b *testing.B) {
params, err := NewParametersFromLiteral(PN10QP27)
if err != nil {
b.Fatal(err)
}
kg := NewKeyGenerator(params)
b.Run("SecretKey", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
kg.GenSecretKey()
}
})
sk := kg.GenSecretKey()
b.Run("BootstrapKey", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
kg.GenBootstrapKey(sk)
}
})
}
-52
View File
@@ -1,52 +0,0 @@
goos: darwin
goarch: arm64
pkg: github.com/luxfi/fhe
cpu: Apple M1 Max
BenchmarkLatticeKeyGen-10 28998 41747 ns/op 15600 B/op 21 allocs/op
BenchmarkLatticePublicKeyGen-10 66368 17420 ns/op 11936 B/op 22 allocs/op
BenchmarkLatticeBootstrapKeyGen-10 8 131860630 ns/op 82447622 B/op 151516 allocs/op
BenchmarkLatticeEncryptBit-10 53984 20809 ns/op 15992 B/op 29 allocs/op
BenchmarkLatticeDecryptBit-10 253042 4521 ns/op 4736 B/op 8 allocs/op
BenchmarkLatticeAND-10 21 52519200 ns/op 1202526 B/op 38009 allocs/op
BenchmarkLatticeOR-10 22 51721345 ns/op 1209729 B/op 38254 allocs/op
BenchmarkLatticeXOR-10 7 161679381 ns/op 3652602 B/op 115121 allocs/op
BenchmarkLatticeNOT-10 990417 1189 ns/op 8856 B/op 11 allocs/op
BenchmarkLatticeNAND-10 21 52048927 ns/op 1199232 B/op 37931 allocs/op
BenchmarkLatticeNOR-10 22 52189896 ns/op 1201428 B/op 37995 allocs/op
BenchmarkLatticeXNOR-10 7 160594298 ns/op 3648886 B/op 115249 allocs/op
BenchmarkLatticeMUX-10 7 158445155 ns/op 3617170 B/op 114060 allocs/op
BenchmarkLatticeEncryptInt8-10 7239 166821 ns/op 128048 B/op 234 allocs/op
BenchmarkLatticeEncryptInt16-10 3524 326558 ns/op 256048 B/op 466 allocs/op
BenchmarkLatticeEncryptInt32-10 1676 663523 ns/op 512048 B/op 930 allocs/op
BenchmarkLatticeDecryptInt8-10 32006 36523 ns/op 37888 B/op 64 allocs/op
BenchmarkLatticeDecryptInt16-10 16202 74022 ns/op 75776 B/op 128 allocs/op
BenchmarkLatticeAdd8-10 1 3502386500 ns/op 81194968 B/op 2559530 allocs/op
BenchmarkLatticeAdd16-10 1 7295119084 ns/op 168213608 B/op 5309943 allocs/op
BenchmarkLatticeSub8-10 1 5199911125 ns/op 115079360 B/op 3629860 allocs/op
BenchmarkLatticeScalarAdd8-10 1 1607502916 ns/op 36169352 B/op 1140974 allocs/op
BenchmarkLatticeEq8-10 1 1739358750 ns/op 37334728 B/op 1180304 allocs/op
BenchmarkLatticeLt8-10 1 2905434333 ns/op 63983496 B/op 2021721 allocs/op
BenchmarkLatticeLe8-10 1 4524679625 ns/op 102752968 B/op 3246519 allocs/op
BenchmarkLatticeGt8-10 1 2781826875 ns/op 64109536 B/op 2025297 allocs/op
BenchmarkLatticeMin8-10 1 3999070792 ns/op 93132400 B/op 2942093 allocs/op
BenchmarkLatticeMax8-10 1 4014468209 ns/op 93031712 B/op 2939102 allocs/op
BenchmarkLatticeBitwiseAnd8-10 3 420482722 ns/op 9683120 B/op 306123 allocs/op
BenchmarkLatticeBitwiseOr8-10 3 429208861 ns/op 9625712 B/op 304241 allocs/op
BenchmarkLatticeBitwiseXor8-10 1 1450445458 ns/op 29048048 B/op 916361 allocs/op
BenchmarkLatticeBitwiseNot8-10 105090 10466 ns/op 70960 B/op 90 allocs/op
BenchmarkLatticeShl8-10 120087 9946 ns/op 35408 B/op 42 allocs/op
BenchmarkLatticeShr8-10 112731 9616 ns/op 35408 B/op 42 allocs/op
BenchmarkLatticeSelect8-10 1 1270980750 ns/op 29034016 B/op 914268 allocs/op
BenchmarkLatticeCastTo16-10 30464 40074 ns/op 141360 B/op 162 allocs/op
BenchmarkLatticePublicEncrypt8-10 3892 308228 ns/op 134328 B/op 274 allocs/op
BenchmarkLatticePublicEncrypt16-10 1890 597936 ns/op 268606 B/op 546 allocs/op
BenchmarkLatticeSerializeCiphertext-10 81741 14369 ns/op 34891 B/op 98 allocs/op
BenchmarkLatticeDeserializeCiphertext-10 58243 20344 ns/op 28576 B/op 255 allocs/op
BenchmarkLatticeSerializeInteger8-10 8608 126824 ns/op 430756 B/op 800 allocs/op
BenchmarkLatticeSerializeInteger16-10 4105 255930 ns/op 873812 B/op 1593 allocs/op
BenchmarkLatticeRNGRandomUint8-10 7045 173022 ns/op 128080 B/op 235 allocs/op
BenchmarkLatticeRNGRandomUint16-10 3469 340920 ns/op 256080 B/op 467 allocs/op
BenchmarkLatticeAllocCiphertext-10 55743 20827 ns/op 15992 B/op 29 allocs/op
BenchmarkLatticeAllocInteger8-10 6997 174253 ns/op 128048 B/op 234 allocs/op
PASS
ok github.com/luxfi/fhe 89.128s
-18
View File
@@ -1,18 +0,0 @@
goos: darwin
goarch: arm64
pkg: github.com/luxfi/fhe
cpu: Apple M1 Max
BenchmarkBitwiseAdd4Bit-10 1 1616760125 ns/op 37581360 B/op 1182665 allocs/op
BenchmarkShortIntEncrypt-10 56146 22166 ns/op 16008 B/op 29 allocs/op
BenchmarkShortIntDecrypt-10 247593 5266 ns/op 4736 B/op 8 allocs/op
BenchmarkIntegerEncryptUint8-10 26554 43922 ns/op 32080 B/op 60 allocs/op
BenchmarkIntegerDecryptUint8-10 124048 9866 ns/op 9472 B/op 16 allocs/op
BenchmarkKeyGen-10 8 136143349 ns/op 82472119 B/op 151550 allocs/op
BenchmarkEncrypt-10 55508 22100 ns/op 15992 B/op 29 allocs/op
BenchmarkDecrypt-10 250294 4946 ns/op 4736 B/op 8 allocs/op
BenchmarkAND-10 22 53778233 ns/op 1231276 B/op 38721 allocs/op
BenchmarkOR-10 22 54273616 ns/op 1231148 B/op 38703 allocs/op
BenchmarkXOR-10 7 157962637 ns/op 3590484 B/op 112912 allocs/op
BenchmarkMUX-10 7 155910143 ns/op 3648014 B/op 114574 allocs/op
PASS
ok github.com/luxfi/fhe 18.051s
-1003
View File
File diff suppressed because it is too large Load Diff
-1071
View File
File diff suppressed because it is too large Load Diff
-1004
View File
File diff suppressed because it is too large Load Diff
-1094
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-564
View File
@@ -1,564 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024-2025, Lux Industries Inc
//
// Optimized Encrypted Comparison for Solidity/EVM
//
// Key innovation: Kogge-Stone parallel prefix comparison with GPU acceleration
// - Traditional: Serial bit-by-bit comparison O(n) depth
// - Optimized: Parallel prefix O(log n) depth with early termination hints
//
// Patent: PAT-FHE-C8 - Encrypted Comparison for Solidity
// For enterprise licensing: [email protected]
#ifndef LUXFHE_ENCRYPTED_COMPARE_H
#define LUXFHE_ENCRYPTED_COMPARE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
// =============================================================================
// Forward Declarations
// =============================================================================
typedef void* LuxFHEEngine;
typedef void* LuxFHECiphertext;
typedef void* LuxFHEInteger;
typedef void* LuxFHECompareContext;
// =============================================================================
// Comparison Result Types
// =============================================================================
// Comparison operations for Solidity FHE precompile
typedef enum {
LUXFHE_CMP_LT = 0, // a < b
LUXFHE_CMP_LE = 1, // a <= b
LUXFHE_CMP_GT = 2, // a > b
LUXFHE_CMP_GE = 3, // a >= b
LUXFHE_CMP_EQ = 4, // a == b
LUXFHE_CMP_NE = 5, // a != b
LUXFHE_CMP_MIN = 6, // min(a, b)
LUXFHE_CMP_MAX = 7 // max(a, b)
} LuxFHECompareOp;
// Integer bit widths matching Solidity FHE types
typedef enum {
LUXFHE_UINT4 = 4,
LUXFHE_UINT8 = 8,
LUXFHE_UINT16 = 16,
LUXFHE_UINT32 = 32,
LUXFHE_UINT64 = 64,
LUXFHE_UINT128 = 128,
LUXFHE_UINT160 = 160, // Ethereum address
LUXFHE_UINT256 = 256
} LuxFHEUintWidth;
// =============================================================================
// Kogge-Stone Parallel Comparison Tree
// =============================================================================
// Configuration for parallel prefix network
typedef struct {
uint32_t num_bits; // Total bits to compare
uint32_t block_size; // Bits per radix block (2 or 4)
uint32_t num_stages; // log2(num_bits) stages
bool use_gpu; // Enable GPU acceleration
bool early_termination; // Enable early termination hints
uint32_t batch_size; // Operations to batch for GPU
} LuxFHEKoggeStoneConfig;
// Stage data for Kogge-Stone tree
typedef struct {
uint32_t stage; // Current stage index
uint32_t stride; // Distance between compared elements
uint32_t num_ops; // Operations in this stage
} LuxFHEKoggeStoneStage;
// =============================================================================
// Parallel Compare Context
// =============================================================================
// Create comparison context with Kogge-Stone configuration
LuxFHECompareContext luxfhe_compare_context_create(
LuxFHEEngine engine,
LuxFHEKoggeStoneConfig config
);
// Free comparison context
void luxfhe_compare_context_free(LuxFHECompareContext ctx);
// Get Kogge-Stone stage info
LuxFHEKoggeStoneStage luxfhe_compare_get_stage_info(
LuxFHECompareContext ctx,
uint32_t stage
);
// =============================================================================
// Core Comparison Operations (Solidity FHE Interface)
// =============================================================================
// FHE.lt(euintN a, euintN b) -> ebool
// Parallel prefix less-than comparison
// Algorithm:
// 1. Compute bit differences: d[i] = a[i] XOR b[i]
// 2. Kogge-Stone parallel prefix to find MSB difference
// 3. Result = b[msb_diff_position]
LuxFHECiphertext luxfhe_lt(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.le(euintN a, euintN b) -> ebool
LuxFHECiphertext luxfhe_le(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.gt(euintN a, euintN b) -> ebool
LuxFHECiphertext luxfhe_gt(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.ge(euintN a, euintN b) -> ebool
LuxFHECiphertext luxfhe_ge(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.eq(euintN a, euintN b) -> ebool
// Parallel XOR-reduction for equality
LuxFHECiphertext luxfhe_eq(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.ne(euintN a, euintN b) -> ebool
LuxFHECiphertext luxfhe_ne(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.min(euintN a, euintN b) -> euintN
// Returns encrypted minimum using oblivious selection
LuxFHEInteger luxfhe_min(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// FHE.max(euintN a, euintN b) -> euintN
LuxFHEInteger luxfhe_max(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
// =============================================================================
// Batch Comparison (GPU-Optimized)
// =============================================================================
// Batch comparison for multiple pairs
// Enables GPU kernel saturation for high throughput
typedef struct {
LuxFHEInteger* a_values; // Array of first operands
LuxFHEInteger* b_values; // Array of second operands
uint32_t count; // Number of comparisons
LuxFHECompareOp op; // Comparison operation
} LuxFHECompareBatch;
// Execute batch comparison
// Returns array of results (ebool for lt/le/gt/ge/eq/ne, euint for min/max)
void* luxfhe_compare_batch(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHECompareBatch* batch
);
// Free batch results
void luxfhe_compare_batch_free(void* results, uint32_t count, LuxFHECompareOp op);
// =============================================================================
// Scalar Comparison (Plaintext Operand)
// =============================================================================
// FHE.lt(euintN a, uintN b) -> ebool (plaintext right operand)
// Optimization: precompute b's bit representation
LuxFHECiphertext luxfhe_lt_scalar(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
const uint8_t* b_bytes,
uint32_t b_len
);
// FHE.eq(euintN a, uintN b) -> ebool (plaintext right operand)
LuxFHECiphertext luxfhe_eq_scalar(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
const uint8_t* b_bytes,
uint32_t b_len
);
// =============================================================================
// GPU Kernel Interface (Metal/CUDA)
// =============================================================================
#ifdef LUXFHE_GPU_ENABLED
// Kogge-Stone parallel prefix kernel configuration
typedef struct {
uint32_t workgroup_size; // Threads per workgroup
uint32_t num_workgroups; // Total workgroups
uint32_t shared_mem_bytes; // Shared memory per workgroup
} LuxFHEGPUKernelConfig;
// Get optimal kernel config for hardware
LuxFHEGPUKernelConfig luxfhe_compare_get_kernel_config(
LuxFHEEngine engine,
uint32_t num_bits,
uint32_t batch_size
);
// Launch Kogge-Stone parallel prefix kernel
// Computes (G, P) pairs: Generate and Propagate signals for comparison
// G[i] = a[i] > b[i], P[i] = a[i] == b[i]
int luxfhe_gpu_kogge_stone_prefix(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEGPUKernelConfig* config,
LuxFHEInteger* a_batch,
LuxFHEInteger* b_batch,
uint32_t batch_size,
LuxFHECiphertext* results
);
// Early termination hint computation
// Returns encrypted hint indicating MSB difference position
LuxFHECiphertext luxfhe_gpu_early_term_hint(
LuxFHEEngine engine,
LuxFHECompareContext ctx,
LuxFHEInteger a,
LuxFHEInteger b
);
#endif // LUXFHE_GPU_ENABLED
// =============================================================================
// Statistics and Profiling
// =============================================================================
typedef struct {
uint64_t total_comparisons; // Total comparison operations
uint64_t gpu_kernel_launches; // GPU kernel invocations
uint64_t early_terminations; // Early termination opportunities
double avg_depth_reduction; // Average depth reduction vs serial
double avg_latency_us; // Average latency in microseconds
double throughput_ops_sec; // Operations per second
} LuxFHECompareStats;
// Get comparison statistics
LuxFHECompareStats luxfhe_compare_get_stats(LuxFHECompareContext ctx);
// Reset statistics
void luxfhe_compare_reset_stats(LuxFHECompareContext ctx);
// =============================================================================
// Solidity Interface Specification
// =============================================================================
/*
* Solidity FHE Precompile Interface for Comparison Operations
*
* Address: 0x0100 (FHE Precompile Base)
*
* Function Selectors:
* lt(bytes32 a, bytes32 b) -> 0x1234... // Returns encrypted bool
* le(bytes32 a, bytes32 b) -> 0x2345...
* gt(bytes32 a, bytes32 b) -> 0x3456...
* ge(bytes32 a, bytes32 b) -> 0x4567...
* eq(bytes32 a, bytes32 b) -> 0x5678...
* ne(bytes32 a, bytes32 b) -> 0x6789...
* min(bytes32 a, bytes32 b) -> 0x789a... // Returns encrypted uint
* max(bytes32 a, bytes32 b) -> 0x89ab...
*
* Input Format:
* - bytes32 handle: Ciphertext handle in global ciphertext store
* - Type info encoded in handle's upper bits
*
* Gas Costs (approximate):
* - lt/gt/le/ge: 50000 + 500 * log2(bit_width) gas
* - eq/ne: 30000 + 300 * log2(bit_width) gas
* - min/max: 80000 + 800 * log2(bit_width) gas
*
* Example Solidity Usage:
*
* import "fhe/FHE.sol";
*
* contract Auction {
* euint256 highestBid;
* eaddress highestBidder;
*
* function bid(einput encryptedBid, bytes calldata proof) external {
* euint256 bidAmount = FHE.asEuint256(encryptedBid, proof);
*
* // Encrypted comparison: is new bid higher?
* ebool isHigher = FHE.gt(bidAmount, highestBid);
*
* // Oblivious selection: update if higher
* highestBid = FHE.select(isHigher, bidAmount, highestBid);
* highestBidder = FHE.select(isHigher,
* FHE.asEaddress(msg.sender),
* highestBidder);
* }
* }
*/
#ifdef __cplusplus
}
#endif
// =============================================================================
// C++ API (when compiled as C++)
// =============================================================================
#ifdef __cplusplus
#include <vector>
#include <memory>
#include <functional>
namespace luxfhe {
namespace compare {
// Encrypted bit type (forward declaration)
class EncryptedBit;
class EncryptedInteger;
// =============================================================================
// Kogge-Stone Parallel Prefix Tree
// =============================================================================
// Generate-Propagate pair for comparison
// G = a > b (generate: this position determines result)
// P = a == b (propagate: defer to higher position)
struct GPPair {
std::shared_ptr<EncryptedBit> G; // Generate signal
std::shared_ptr<EncryptedBit> P; // Propagate signal
};
// Kogge-Stone operator: combines two GP pairs
// (G1, P1) o (G0, P0) = (G1 OR (P1 AND G0), P1 AND P0)
class KoggeStoneOp {
public:
virtual ~KoggeStoneOp() = default;
// Combine two GP pairs homomorphically
virtual GPPair combine(const GPPair& high, const GPPair& low) = 0;
};
// =============================================================================
// ParallelCompare Class
// =============================================================================
class ParallelCompare {
public:
// Configuration
struct Config {
uint32_t num_bits = 256;
uint32_t block_size = 4;
bool use_gpu = true;
bool early_termination = true;
uint32_t batch_size = 1024;
};
// Constructor
explicit ParallelCompare(Config config);
~ParallelCompare();
// Disable copy, enable move
ParallelCompare(const ParallelCompare&) = delete;
ParallelCompare& operator=(const ParallelCompare&) = delete;
ParallelCompare(ParallelCompare&&) noexcept;
ParallelCompare& operator=(ParallelCompare&&) noexcept;
// =========================================================================
// Core Comparison (Kogge-Stone Algorithm)
// =========================================================================
// Less-than comparison using parallel prefix
// Depth: O(log n) vs O(n) for serial
std::shared_ptr<EncryptedBit> lessThan(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// Equality using parallel XOR-reduction
std::shared_ptr<EncryptedBit> equal(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// =========================================================================
// Derived Operations
// =========================================================================
std::shared_ptr<EncryptedBit> lessEqual(
const EncryptedInteger& a,
const EncryptedInteger& b
);
std::shared_ptr<EncryptedBit> greaterThan(
const EncryptedInteger& a,
const EncryptedInteger& b
);
std::shared_ptr<EncryptedBit> greaterEqual(
const EncryptedInteger& a,
const EncryptedInteger& b
);
std::shared_ptr<EncryptedBit> notEqual(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// =========================================================================
// Selection Operations
// =========================================================================
// Oblivious minimum: returns a if a < b, else b
std::shared_ptr<EncryptedInteger> min(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// Oblivious maximum
std::shared_ptr<EncryptedInteger> max(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// Oblivious selection: returns a if cond is true, else b
std::shared_ptr<EncryptedInteger> select(
const EncryptedBit& cond,
const EncryptedInteger& a,
const EncryptedInteger& b
);
// =========================================================================
// Batch Operations (GPU-Optimized)
// =========================================================================
std::vector<std::shared_ptr<EncryptedBit>> batchLessThan(
const std::vector<EncryptedInteger>& a_vec,
const std::vector<EncryptedInteger>& b_vec
);
std::vector<std::shared_ptr<EncryptedBit>> batchEqual(
const std::vector<EncryptedInteger>& a_vec,
const std::vector<EncryptedInteger>& b_vec
);
// =========================================================================
// Scalar Comparisons (Optimized)
// =========================================================================
std::shared_ptr<EncryptedBit> lessThanScalar(
const EncryptedInteger& a,
const std::vector<uint8_t>& b_plaintext
);
std::shared_ptr<EncryptedBit> equalScalar(
const EncryptedInteger& a,
const std::vector<uint8_t>& b_plaintext
);
private:
class Impl;
std::unique_ptr<Impl> impl_;
// Kogge-Stone tree building
std::vector<GPPair> buildGPPairs(
const EncryptedInteger& a,
const EncryptedInteger& b
);
// Parallel prefix computation
GPPair parallelPrefix(const std::vector<GPPair>& gp_pairs);
// GPU kernel dispatch
void dispatchGPUKernel(
const std::vector<GPPair>& gp_pairs,
uint32_t stage,
uint32_t stride
);
};
// =============================================================================
// GPU Kernel Launcher
// =============================================================================
class GPUCompareKernel {
public:
struct LaunchParams {
uint32_t workgroup_size = 256;
uint32_t num_workgroups = 0; // 0 = auto
size_t shared_mem_bytes = 0;
};
virtual ~GPUCompareKernel() = default;
// Launch Kogge-Stone stage kernel
// Each stage computes GP pairs with distance 2^stage
virtual void launchKoggeStoneStage(
const LaunchParams& params,
std::vector<GPPair>& gp_pairs,
uint32_t stage
) = 0;
// Launch XOR-reduction kernel for equality
virtual void launchXorReduction(
const LaunchParams& params,
std::vector<std::shared_ptr<EncryptedBit>>& xor_bits
) = 0;
// Launch oblivious selection kernel
virtual void launchSelect(
const LaunchParams& params,
const EncryptedBit& cond,
const EncryptedInteger& a,
const EncryptedInteger& b,
EncryptedInteger& result
) = 0;
};
// Factory for platform-specific kernel
std::unique_ptr<GPUCompareKernel> createGPUCompareKernel();
} // namespace compare
} // namespace luxfhe
#endif // __cplusplus
#endif // LUXFHE_ENCRYPTED_COMPARE_H
-1151
View File
File diff suppressed because it is too large Load Diff
-242
View File
@@ -1,242 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2025, Lux Industries Inc
//
// C bridge header for OpenFHE BinFHE (TFHE) operations
// This header defines the C interface that Go calls via CGO
#ifndef TFHE_BRIDGE_H
#define TFHE_BRIDGE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
// Opaque handle types
typedef void* TfheContext;
typedef void* TfheSecretKey;
typedef void* TfhePublicKey;
typedef void* TfheCiphertext;
typedef void* TfheBootstrapKey;
// Security levels matching OpenFHE BINFHE_PARAMSET
typedef enum {
TFHE_TOY = 0, // ~16-bit security (testing only)
TFHE_STD128 = 1, // 128-bit security (CGGI/GINX)
TFHE_STD128_AP = 2, // 128-bit security (AP variant)
TFHE_STD128_LMKCDEY = 3, // 128-bit security (LMKCDEY - fastest)
TFHE_STD192 = 4, // 192-bit security
TFHE_STD256 = 5 // 256-bit security
} TfheSecurityLevel;
// Bootstrapping method
typedef enum {
TFHE_METHOD_GINX = 0, // GINX (default)
TFHE_METHOD_AP = 1, // AP variant
TFHE_METHOD_LMKCDEY = 2 // LMKCDEY (fastest)
} TfheMethod;
// =============================================================================
// Context Management
// =============================================================================
// Create a new TFHE context with specified security level and method
TfheContext tfhe_context_new(TfheSecurityLevel level, TfheMethod method);
// Free a TFHE context
void tfhe_context_free(TfheContext ctx);
// Get version of the bridge library
uint32_t tfhe_version(void);
// =============================================================================
// Key Generation
// =============================================================================
// Generate a secret key
TfheSecretKey tfhe_keygen(TfheContext ctx);
// Free a secret key
void tfhe_secretkey_free(TfheSecretKey sk);
// Generate bootstrap key (required for gate evaluation)
int tfhe_bootstrap_keygen(TfheContext ctx, TfheSecretKey sk);
// Generate key switching key
int tfhe_keyswitch_keygen(TfheContext ctx, TfheSecretKey sk);
// Check if bootstrap key is generated
bool tfhe_has_bootstrap_key(TfheContext ctx);
// =============================================================================
// Public Key Generation
// =============================================================================
// Generate a public key from secret key
TfhePublicKey tfhe_public_keygen(TfheContext ctx, TfheSecretKey sk);
// Free a public key
void tfhe_public_key_free(TfhePublicKey pk);
// Serialize public key to bytes
int tfhe_publickey_serialize(TfhePublicKey pk, uint8_t** out, size_t* out_len);
// Deserialize public key from bytes
TfhePublicKey tfhe_publickey_deserialize(TfheContext ctx, const uint8_t* data, size_t len);
// =============================================================================
// Encryption / Decryption (Boolean)
// =============================================================================
// Encrypt a boolean value (0 or 1)
TfheCiphertext tfhe_encrypt(TfheContext ctx, TfheSecretKey sk, int value);
// Encrypt a bit (alias for tfhe_encrypt)
TfheCiphertext tfhe_encrypt_bit(TfheContext ctx, TfheSecretKey sk, int value);
// Encrypt a bit with public key
TfheCiphertext tfhe_encrypt_bit_public(TfheContext ctx, TfhePublicKey pk, int value);
// Decrypt a ciphertext to boolean
int tfhe_decrypt(TfheContext ctx, TfheSecretKey sk, TfheCiphertext ct);
// Decrypt a bit (alias for tfhe_decrypt)
int tfhe_decrypt_bit(TfheContext ctx, TfheSecretKey sk, TfheCiphertext ct);
// Free a ciphertext
void tfhe_ciphertext_free(TfheCiphertext ct);
// Free a secret key (alias for backward compatibility)
void tfhe_secret_key_free(TfheSecretKey sk);
// Clone a ciphertext
TfheCiphertext tfhe_ciphertext_clone(TfheCiphertext ct);
// =============================================================================
// Boolean Gates (with bootstrapping)
// =============================================================================
TfheCiphertext tfhe_and(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_or(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_xor(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_nand(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_nor(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_xnor(TfheContext ctx, TfheCiphertext ct1, TfheCiphertext ct2);
TfheCiphertext tfhe_not(TfheContext ctx, TfheCiphertext ct);
TfheCiphertext tfhe_mux(TfheContext ctx, TfheCiphertext sel, TfheCiphertext ct1, TfheCiphertext ct2);
// =============================================================================
// Integer Operations (radix representation)
// =============================================================================
// Integer ciphertext handle
typedef void* TfheInteger;
// Integer types
typedef enum {
TFHE_UINT4 = 4,
TFHE_UINT8 = 8,
TFHE_UINT16 = 16,
TFHE_UINT32 = 32,
TFHE_UINT64 = 64,
TFHE_UINT128 = 128,
TFHE_UINT160 = 160,
TFHE_UINT256 = 256
} TfheIntType;
// Encrypt an integer
TfheInteger tfhe_encrypt_integer(TfheContext ctx, TfheSecretKey sk, int64_t value, int bitLen);
// Encrypt an integer with public key
TfheInteger tfhe_encrypt_integer_public(TfheContext ctx, TfhePublicKey pk, int64_t value, int bitLen);
// Decrypt an integer
int64_t tfhe_decrypt_integer(TfheContext ctx, TfheSecretKey sk, TfheInteger ct);
// Free an integer ciphertext
void tfhe_integer_free(TfheInteger ct);
// Clone an integer ciphertext
TfheInteger tfhe_integer_clone(TfheInteger ct);
// Get the type of an integer ciphertext
TfheIntType tfhe_integer_type(TfheInteger ct);
// =============================================================================
// Integer Arithmetic
// =============================================================================
TfheInteger tfhe_add(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_sub(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_neg(TfheContext ctx, TfheInteger a);
TfheInteger tfhe_add_scalar(TfheContext ctx, TfheInteger a, int64_t scalar);
TfheInteger tfhe_sub_scalar(TfheContext ctx, TfheInteger a, int64_t scalar);
TfheInteger tfhe_mul_scalar(TfheContext ctx, TfheInteger a, int64_t scalar);
// =============================================================================
// Integer Comparisons
// =============================================================================
TfheCiphertext tfhe_eq(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheCiphertext tfhe_ne(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheCiphertext tfhe_lt(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheCiphertext tfhe_le(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheCiphertext tfhe_gt(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheCiphertext tfhe_ge(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_min(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_max(TfheContext ctx, TfheInteger a, TfheInteger b);
// =============================================================================
// Integer Bitwise Operations
// =============================================================================
TfheInteger tfhe_bitwise_and(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_bitwise_or(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_bitwise_xor(TfheContext ctx, TfheInteger a, TfheInteger b);
TfheInteger tfhe_bitwise_not(TfheContext ctx, TfheInteger a);
TfheInteger tfhe_shl(TfheContext ctx, TfheInteger a, int bits);
TfheInteger tfhe_shr(TfheContext ctx, TfheInteger a, int bits);
// =============================================================================
// Control Flow
// =============================================================================
TfheInteger tfhe_select(TfheContext ctx, TfheCiphertext cond, TfheInteger if_true, TfheInteger if_false);
TfheInteger tfhe_cast_to(TfheContext ctx, TfheInteger a, int target_bitlen);
// =============================================================================
// Serialization
// =============================================================================
// Serialize ciphertext to bytes (returns malloc'd buffer, caller must free)
uint8_t* tfhe_serialize_ciphertext(TfheContext ctx, TfheCiphertext ct, size_t* out_len);
// Deserialize ciphertext from bytes
TfheCiphertext tfhe_deserialize_ciphertext(TfheContext ctx, const uint8_t* data, size_t len);
// Serialize secret key to bytes (returns malloc'd buffer, caller must free)
uint8_t* tfhe_serialize_secret_key(TfheContext ctx, TfheSecretKey sk, size_t* out_len);
// Deserialize secret key from bytes
TfheSecretKey tfhe_deserialize_secret_key(TfheContext ctx, const uint8_t* data, size_t len);
// Serialize public key to bytes (returns malloc'd buffer, caller must free)
uint8_t* tfhe_serialize_public_key(TfheContext ctx, TfhePublicKey pk, size_t* out_len);
// Deserialize public key from bytes
TfhePublicKey tfhe_deserialize_public_key(TfheContext ctx, const uint8_t* data, size_t len);
// Serialize integer ciphertext to bytes (returns malloc'd buffer, caller must free)
uint8_t* tfhe_serialize_integer(TfheContext ctx, TfheInteger ct, size_t* out_len);
// Deserialize integer ciphertext from bytes
TfheInteger tfhe_deserialize_integer(TfheContext ctx, const uint8_t* data, size_t len);
#ifdef __cplusplus
}
#endif
#endif // TFHE_BRIDGE_H
-149
View File
@@ -1,149 +0,0 @@
// Command fhe-gateway runs the blockchain event listener and job gateway.
package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/luxfi/fhe/internal/queue"
"github.com/luxfi/fhe/internal/storage"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
func run() error {
var (
redisAddr = flag.String("redis", "localhost:6379", "Redis address")
redisDB = flag.Int("redis-db", 0, "Redis database number")
queueName = flag.String("queue", "default", "queue name")
storagePath = flag.String("storage", "/tmp/fhe-storage", "ciphertext storage path")
httpAddr = flag.String("http", ":8080", "HTTP API address")
rpcURL = flag.String("rpc", "", "Blockchain RPC URL")
)
flag.Parse()
log.Printf("FHE Gateway starting...")
log.Printf(" Redis: %s", *redisAddr)
log.Printf(" Storage: %s", *storagePath)
log.Printf(" HTTP: %s", *httpAddr)
if *rpcURL != "" {
log.Printf(" RPC: %s", *rpcURL)
}
// Queue.
q, err := queue.NewRedisQueue(queue.RedisConfig{
Addr: *redisAddr,
DB: *redisDB,
}, *queueName)
if err != nil {
return fmt.Errorf("create queue: %w", err)
}
defer q.Close()
// Storage.
store, err := storage.NewFileStorage(*storagePath)
if err != nil {
return fmt.Errorf("create storage: %w", err)
}
// Context with cancellation.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// HTTP API.
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
mux.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"status":"running"}`)
})
mux.HandleFunc("/job/", func(w http.ResponseWriter, r *http.Request) {
jobID := r.URL.Path[len("/job/"):]
if jobID == "" {
http.Error(w, "job ID required", http.StatusBadRequest)
return
}
job, err := q.Get(r.Context(), jobID)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"id":"%s","status":%d,"result":"%s","error":"%s"}`,
job.ID, job.Status, job.ResultHandle, job.Error)
})
// Store ciphertext endpoint
mux.HandleFunc("/store", func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "POST required", http.StatusMethodNotAllowed)
return
}
data := make([]byte, r.ContentLength)
if _, err := r.Body.Read(data); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
handle, err := store.Store(r.Context(), data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"handle":"%s"}`, handle)
})
server := &http.Server{
Addr: *httpAddr,
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
}
go func() {
log.Printf("HTTP server starting on %s", *httpAddr)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Printf("HTTP server error: %v", err)
}
}()
// Wait for shutdown signal.
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigCh
log.Printf("Received signal: %s", sig.String())
// Graceful shutdown.
shutdownCtx, shutdownCancel := context.WithTimeout(ctx, 30*time.Second)
defer shutdownCancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Printf("HTTP server shutdown error: %v", err)
}
log.Println("Shutdown complete")
return nil
}
-99
View File
@@ -1,99 +0,0 @@
//go:build cgo
// Lux FHE Server - Standalone FHE service node
//
// Provides:
// - FHE operations (encrypt, decrypt, evaluate)
// - GPU-accelerated batch operations via MLX
// - Threshold FHE decryption network
// - ZK verification service
// - Key management
//
// Run as sidecar for Solidity stack:
//
// fhe-server -addr :8448 -gpu
package main
import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/luxfi/fhe/server"
)
func main() {
var (
addr = flag.String("addr", ":8448", "HTTP server address")
threshold = flag.Bool("threshold", false, "Enable threshold FHE mode")
parties = flag.Int("parties", 5, "Number of threshold parties")
dataDir = flag.String("data", "./data", "Data directory for keys")
gpuMode = flag.Bool("gpu", false, "Enable GPU acceleration (Metal/CUDA)")
batchSize = flag.Int("batch", 32, "Batch size for GPU operations")
)
flag.Parse()
log.Printf("Lux FHE Server starting...")
log.Printf(" Address: %s", *addr)
log.Printf(" GPU mode: %v", *gpuMode)
log.Printf(" Threshold mode: %v", *threshold)
if *threshold {
log.Printf(" Parties: %d", *parties)
}
if *gpuMode {
log.Printf(" Batch size: %d", *batchSize)
}
// Create server config
cfg := server.Config{
Address: *addr,
ThresholdMode: *threshold,
NumParties: *parties,
DataDir: *dataDir,
GPUMode: *gpuMode,
BatchSize: *batchSize,
}
// Initialize FHE server
srv, err := server.New(cfg)
if err != nil {
log.Fatalf("Failed to create server: %v", err)
}
// Setup HTTP server
httpServer := &http.Server{
Addr: cfg.Address,
Handler: srv.Handler(),
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
}
// Start server in goroutine
go func() {
log.Printf("FHE Server listening on %s", cfg.Address)
if err := httpServer.ListenAndServe(); err != http.ErrServerClosed {
log.Fatalf("HTTP server error: %v", err)
}
}()
// Wait for shutdown signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down FHE Server...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := httpServer.Shutdown(ctx); err != nil {
log.Printf("Server shutdown error: %v", err)
}
fmt.Println("FHE Server stopped")
}
-325
View File
@@ -1,325 +0,0 @@
// Command fhe-worker runs FHE computation workers.
package main
import (
"context"
"errors"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"sync"
"sync/atomic"
"syscall"
"time"
"github.com/luxfi/fhe"
"github.com/luxfi/fhe/internal/queue"
"github.com/luxfi/fhe/internal/storage"
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
func run() error {
var (
numWorkers = flag.Int("workers", 4, "number of worker goroutines")
redisAddr = flag.String("redis", "localhost:6379", "Redis address")
redisDB = flag.Int("redis-db", 0, "Redis database number")
queueName = flag.String("queue", "default", "queue name")
storagePath = flag.String("storage", "/tmp/fhe-storage", "ciphertext storage path")
metricsAddr = flag.String("metrics", ":9090", "metrics server address")
)
flag.Parse()
log.Printf("FHE Worker starting...")
log.Printf(" Workers: %d", *numWorkers)
log.Printf(" Redis: %s", *redisAddr)
log.Printf(" Storage: %s", *storagePath)
log.Printf(" Metrics: %s", *metricsAddr)
// Queue.
q, err := queue.NewRedisQueue(queue.RedisConfig{
Addr: *redisAddr,
DB: *redisDB,
}, *queueName)
if err != nil {
return fmt.Errorf("create queue: %w", err)
}
defer q.Close()
// Storage.
store, err := storage.NewFileStorage(*storagePath)
if err != nil {
return fmt.Errorf("create storage: %w", err)
}
// Initialize FHE parameters
params, err := fhe.NewParametersFromLiteral(fhe.PN10QP27)
if err != nil {
return fmt.Errorf("create FHE parameters: %w", err)
}
kgen := fhe.NewKeyGenerator(params)
sk := kgen.GenSecretKey()
bsk := kgen.GenBootstrapKey(sk)
// Worker pool.
pool := &WorkerPool{
numWorkers: *numWorkers,
queue: q,
storage: store,
params: params,
bsk: bsk,
sk: sk,
}
// Context with cancellation.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Start workers.
if err := pool.Start(ctx); err != nil {
return fmt.Errorf("start workers: %w", err)
}
// Metrics server.
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "# HELP fhe_operations_total Total FHE operations\n")
fmt.Fprintf(w, "# TYPE fhe_operations_total counter\n")
fmt.Fprintf(w, "fhe_operations_total{status=\"success\"} %d\n", pool.successCount.Load())
fmt.Fprintf(w, "fhe_operations_total{status=\"failure\"} %d\n", pool.failureCount.Load())
})
server := &http.Server{
Addr: *metricsAddr,
Handler: mux,
}
go func() {
log.Printf("Metrics server starting on %s", *metricsAddr)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Printf("Metrics server error: %v", err)
}
}()
// Wait for shutdown signal.
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigCh
log.Printf("Received signal: %s", sig.String())
// Graceful shutdown.
shutdownCtx, shutdownCancel := context.WithTimeout(ctx, 30*time.Second)
defer shutdownCancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Printf("Metrics server shutdown error: %v", err)
}
if err := pool.Stop(); err != nil {
log.Printf("Worker pool shutdown error: %v", err)
}
log.Println("Shutdown complete")
return nil
}
// WorkerPool manages a pool of FHE computation workers.
type WorkerPool struct {
numWorkers int
queue queue.Queue
storage storage.Storage
params fhe.Parameters
bsk *fhe.BootstrapKey
sk *fhe.SecretKey
wg sync.WaitGroup
cancel context.CancelFunc
running atomic.Bool
successCount atomic.Int64
failureCount atomic.Int64
}
// Start starts the worker pool.
func (p *WorkerPool) Start(ctx context.Context) error {
if p.running.Load() {
return errors.New("pool already running")
}
ctx, p.cancel = context.WithCancel(ctx)
p.running.Store(true)
log.Printf("Starting %d workers", p.numWorkers)
for i := 0; i < p.numWorkers; i++ {
p.wg.Add(1)
go p.worker(ctx, i)
}
return nil
}
// Stop gracefully stops the worker pool.
func (p *WorkerPool) Stop() error {
if !p.running.Load() {
return nil
}
log.Println("Stopping worker pool...")
p.cancel()
done := make(chan struct{})
go func() {
p.wg.Wait()
close(done)
}()
select {
case <-done:
log.Println("Worker pool stopped")
case <-time.After(30 * time.Second):
log.Println("Shutdown timeout exceeded")
return errors.New("shutdown timeout")
}
p.running.Store(false)
return nil
}
func (p *WorkerPool) worker(ctx context.Context, id int) {
defer p.wg.Done()
log.Printf("Worker %d started", id)
for {
select {
case <-ctx.Done():
log.Printf("Worker %d stopping", id)
return
default:
}
job, err := p.queue.Pop(ctx)
if err != nil {
if errors.Is(err, context.Canceled) {
return
}
log.Printf("Worker %d: failed to pop job: %v", id, err)
time.Sleep(time.Second)
continue
}
p.processJob(ctx, id, job)
}
}
func (p *WorkerPool) processJob(ctx context.Context, workerID int, job *queue.Job) {
log.Printf("Worker %d: processing job %s (op=%d)", workerID, job.ID, job.Operation)
// Mark as processing.
job.Status = queue.StatusProcessing
if err := p.queue.Update(ctx, job); err != nil {
log.Printf("Worker %d: failed to update job status: %v", workerID, err)
}
// Load ciphertexts
lhsData, err := p.storage.Load(ctx, storage.Handle(job.LHSHandle))
if err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("load lhs: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
// Create evaluator
bitwiseEval := fhe.NewBitwiseEvaluator(p.params, p.bsk, p.sk)
// Deserialize LHS
lhs := new(fhe.BitCiphertext)
if err := lhs.UnmarshalBinary(lhsData); err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("unmarshal lhs: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
var result *fhe.BitCiphertext
// Execute operation
switch job.Operation {
case 0: // Add
rhsData, err := p.storage.Load(ctx, storage.Handle(job.RHSHandle))
if err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("load rhs: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
rhs := new(fhe.BitCiphertext)
if err := rhs.UnmarshalBinary(rhsData); err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("unmarshal rhs: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
result, err = bitwiseEval.Add(lhs, rhs)
if err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("add: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
default:
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("unsupported operation: %d", job.Operation)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
// Store result
resultData, err := result.MarshalBinary()
if err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("marshal result: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
handle, err := p.storage.Store(ctx, resultData)
if err != nil {
job.Status = queue.StatusFailed
job.Error = fmt.Sprintf("store result: %v", err)
p.queue.Update(ctx, job)
p.failureCount.Add(1)
return
}
// Update job status.
job.Status = queue.StatusCompleted
job.ResultHandle = string(handle)
if err := p.queue.Update(ctx, job); err != nil {
log.Printf("Worker %d: failed to update job result: %v", workerID, err)
}
p.successCount.Add(1)
log.Printf("Worker %d: job %s completed", workerID, job.ID)
}
-289
View File
@@ -1,289 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
//go:build profile
// Command profile runs performance profiling on FHE operations.
//
// Usage:
//
// go build -tags profile -o profile ./cmd/profile
// ./profile -cpu=cpu.prof -mem=mem.prof -iterations=1000
//
// Analyze profiles:
//
// go tool pprof -http=:8080 cpu.prof
// go tool pprof -http=:8081 mem.prof
package main
import (
"flag"
"fmt"
"os"
"runtime"
"time"
"github.com/luxfi/fhe"
)
var (
cpuProfile = flag.String("cpu", "", "write cpu profile to file")
memProfile = flag.String("mem", "", "write memory profile to file")
iterations = flag.Int("iterations", 100, "number of iterations for each operation")
operation = flag.String("op", "all", "operation to profile: all, keygen, encrypt, gates, circuit")
verbose = flag.Bool("v", false, "verbose output")
)
func main() {
flag.Parse()
// Configure profiling
config := fhe.ProfileConfig{
CPUProfile: *cpuProfile,
MemProfile: *memProfile,
}
profiler := fhe.NewProfiler(config)
if err := profiler.Start(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to start profiler: %v\n", err)
os.Exit(1)
}
defer profiler.Stop()
// Run profiling workload
fmt.Printf("Running %d iterations of '%s'\n", *iterations, *operation)
fmt.Printf("GOMAXPROCS: %d\n", runtime.GOMAXPROCS(0))
switch *operation {
case "all":
profileAll()
case "keygen":
profileKeyGen()
case "encrypt":
profileEncrypt()
case "gates":
profileGates()
case "circuit":
profileCircuit()
default:
fmt.Fprintf(os.Stderr, "Unknown operation: %s\n", *operation)
os.Exit(1)
}
fhe.PrintMemStats()
}
func profileAll() {
profileKeyGen()
profileEncrypt()
profileGates()
profileCircuit()
}
func profileKeyGen() {
fmt.Println("\n=== Key Generation ===")
params, err := fhe.NewParametersFromLiteral(fhe.PN10QP27)
if err != nil {
panic(err)
}
kg := fhe.NewKeyGenerator(params)
// Secret key generation
timer := fhe.NewTimer("SecretKey generation")
for i := 0; i < *iterations; i++ {
kg.GenSecretKey()
}
d := timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Public key generation
sk := kg.GenSecretKey()
timer = fhe.NewTimer("PublicKey generation")
for i := 0; i < *iterations; i++ {
kg.GenPublicKey(sk)
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Bootstrap key generation (fewer iterations - expensive)
bkIter := *iterations / 10
if bkIter < 1 {
bkIter = 1
}
timer = fhe.NewTimer(fmt.Sprintf("BootstrapKey generation (%d iter)", bkIter))
for i := 0; i < bkIter; i++ {
kg.GenBootstrapKey(sk)
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(bkIter))
}
func profileEncrypt() {
fmt.Println("\n=== Encryption/Decryption ===")
params, err := fhe.NewParametersFromLiteral(fhe.PN10QP27)
if err != nil {
panic(err)
}
kg := fhe.NewKeyGenerator(params)
sk := kg.GenSecretKey()
enc := fhe.NewEncryptor(params, sk)
dec := fhe.NewDecryptor(params, sk)
// Bit encryption
timer := fhe.NewTimer("Bit encryption")
for i := 0; i < *iterations; i++ {
enc.Encrypt(true)
}
d := timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Bit decryption
ct := enc.Encrypt(true)
timer = fhe.NewTimer("Bit decryption")
for i := 0; i < *iterations; i++ {
dec.Decrypt(ct)
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Byte encryption
timer = fhe.NewTimer("Byte encryption")
for i := 0; i < *iterations; i++ {
enc.EncryptByte(0x42)
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Byte decryption
ctByte := enc.EncryptByte(0x42)
timer = fhe.NewTimer("Byte decryption")
for i := 0; i < *iterations; i++ {
dec.DecryptByte(ctByte)
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
}
func profileGates() {
fmt.Println("\n=== Boolean Gates ===")
params, err := fhe.NewParametersFromLiteral(fhe.PN10QP27)
if err != nil {
panic(err)
}
kg := fhe.NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := fhe.NewEncryptor(params, sk)
eval := fhe.NewEvaluator(params, bk, sk)
ct1 := enc.Encrypt(true)
ct2 := enc.Encrypt(false)
gates := []struct {
name string
fn func() error
}{
{"AND", func() error { _, err := eval.AND(ct1, ct2); return err }},
{"OR", func() error { _, err := eval.OR(ct1, ct2); return err }},
{"XOR", func() error { _, err := eval.XOR(ct1, ct2); return err }},
{"NAND", func() error { _, err := eval.NAND(ct1, ct2); return err }},
{"NOR", func() error { _, err := eval.NOR(ct1, ct2); return err }},
{"XNOR", func() error { _, err := eval.XNOR(ct1, ct2); return err }},
{"NOT", func() error { eval.NOT(ct1); return nil }},
}
for _, gate := range gates {
timer := fhe.NewTimer(gate.name)
for i := 0; i < *iterations; i++ {
if err := gate.fn(); err != nil {
panic(err)
}
}
d := timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
}
// MUX
ct3 := enc.Encrypt(true)
timer := fhe.NewTimer("MUX")
for i := 0; i < *iterations; i++ {
_, err := eval.MUX(ct1, ct2, ct3)
if err != nil {
panic(err)
}
}
d := timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
}
func profileCircuit() {
fmt.Println("\n=== Circuit Evaluation ===")
params, err := fhe.NewParametersFromLiteral(fhe.PN10QP27)
if err != nil {
panic(err)
}
kg := fhe.NewKeyGenerator(params)
sk := kg.GenSecretKey()
bk := kg.GenBootstrapKey(sk)
enc := fhe.NewEncryptor(params, sk)
eval := fhe.NewEvaluator(params, bk, sk)
// 8-bit adder circuit
a := enc.EncryptByte(0x42)
b := enc.EncryptByte(0x37)
timer := fhe.NewTimer("8-bit Addition")
for i := 0; i < *iterations; i++ {
carry := enc.Encrypt(false)
for bit := 0; bit < 8; bit++ {
// Full adder for each bit
axorb, err := eval.XOR(a[bit], b[bit])
if err != nil {
panic(err)
}
_, err = eval.XOR(axorb, carry)
if err != nil {
panic(err)
}
aandb, err := eval.AND(a[bit], b[bit])
if err != nil {
panic(err)
}
candaxorb, err := eval.AND(carry, axorb)
if err != nil {
panic(err)
}
carry, err = eval.OR(aandb, candaxorb)
if err != nil {
panic(err)
}
}
}
d := timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
// Gate chain (simulating complex circuit)
n := 16
cts := make([]*fhe.Ciphertext, n)
for i := 0; i < n; i++ {
cts[i] = enc.Encrypt(i%2 == 0)
}
timer = fhe.NewTimer(fmt.Sprintf("AND chain (%d gates)", n-1))
for i := 0; i < *iterations; i++ {
result := cts[0]
for j := 1; j < n; j++ {
result, err = eval.AND(result, cts[j])
if err != nil {
panic(err)
}
}
}
d = timer.Stop()
fmt.Printf(" Average: %v/op\n", d/time.Duration(*iterations))
fmt.Printf(" Per gate: %v\n", d/time.Duration(*iterations*(n-1)))
}
-132
View File
@@ -1,132 +0,0 @@
name: luxfhe
services:
# =============================================================================
# FHE Server - Standard Mode (port 8448)
# =============================================================================
server:
build:
context: .
target: server
image: ghcr.io/luxfi/fhe/server:latest
container_name: luxfhe-server
ports:
- "8448:8448"
volumes:
- fhe-data:/app/data
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:8448/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 5s
# =============================================================================
# FHE Server - Threshold Mode (port 8449)
# =============================================================================
server-threshold:
build:
context: .
target: server
image: ghcr.io/luxfi/fhe/server:latest
container_name: luxfhe-threshold
ports:
- "8449:8449"
command: ["-addr", ":8449", "-threshold", "-parties", "5"]
volumes:
- fhe-threshold-data:/app/data
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:8449/health"]
interval: 10s
timeout: 5s
retries: 5
profiles:
- threshold
# =============================================================================
# FHE Gateway - Blockchain Event Listener (port 8080)
# =============================================================================
gateway:
build:
context: .
target: gateway
image: ghcr.io/luxfi/fhe/gateway:latest
container_name: luxfhe-gateway
ports:
- "8080:8080"
environment:
- RPC_URL=${RPC_URL:-http://host.docker.internal:8545}
command: ["-http", ":8080", "-redis", "redis:6379", "-storage", "/app/data"]
volumes:
- fhe-storage:/app/data
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 5
profiles:
- coprocessor
# =============================================================================
# FHE Worker - Computation Workers (port 9090 metrics)
# =============================================================================
worker:
build:
context: .
target: worker
image: ghcr.io/luxfi/fhe/worker:latest
deploy:
replicas: 2
command: ["-redis", "redis:6379", "-storage", "/app/data", "-workers", "4", "-metrics", ":9090"]
volumes:
- fhe-storage:/app/data
depends_on:
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "-O", "-", "http://localhost:9090/health"]
interval: 10s
timeout: 5s
retries: 5
profiles:
- coprocessor
# =============================================================================
# Redis - Job Queue
# =============================================================================
redis:
image: redis:7-alpine
container_name: luxfhe-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
profiles:
- coprocessor
# =============================================================================
# Anvil - Local Blockchain for Testing
# =============================================================================
anvil:
image: ghcr.io/foundry-rs/foundry:latest
container_name: luxfhe-anvil
entrypoint: ["anvil"]
command: ["--host", "0.0.0.0", "--chain-id", "96369"]
ports:
- "8545:8545"
profiles:
- contracts
volumes:
fhe-data:
fhe-threshold-data:
fhe-storage:
redis-data:
-99
View File
@@ -1,99 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
package fhe
import (
"github.com/luxfi/lattice/v7/core/rlwe"
"github.com/luxfi/lattice/v7/ring"
)
// Decryptor decrypts FHE ciphertexts to boolean values
type Decryptor struct {
params Parameters
decryptor *rlwe.Decryptor
ringQ *ring.Ring
}
// NewDecryptor creates a new decryptor from secret key
func NewDecryptor(params Parameters, sk *SecretKey) *Decryptor {
return &Decryptor{
params: params,
decryptor: rlwe.NewDecryptor(params.paramsLWE, sk.SKLWE),
ringQ: params.paramsLWE.RingQ(),
}
}
// Decrypt decrypts a ciphertext to a boolean
func (dec *Decryptor) Decrypt(ct *Ciphertext) bool {
pt := rlwe.NewPlaintext(dec.params.paramsLWE, ct.Level())
dec.decryptor.Decrypt(ct.Ciphertext, pt)
if pt.IsNTT {
dec.ringQ.INTT(pt.Value, pt.Value)
}
// Get the constant term
c := pt.Value.Coeffs[0][0]
q := dec.params.QLWE()
qHalf := q >> 1
// Decode:
// - true was encoded as Q/8, so c ∈ [0, Q/2) means true
// - false was encoded as 7Q/8, so c ∈ [Q/2, Q) means false
return c < qHalf
}
// DecryptBit returns the decrypted bit as int (0 or 1)
func (dec *Decryptor) DecryptBit(ct *Ciphertext) int {
if dec.Decrypt(ct) {
return 1
}
return 0
}
// DecryptByte decrypts 8 ciphertexts to a byte
func (dec *Decryptor) DecryptByte(cts [8]*Ciphertext) byte {
var b byte
for i := 0; i < 8; i++ {
if dec.Decrypt(cts[i]) {
b |= 1 << i
}
}
return b
}
// DecryptUint32 decrypts 32 ciphertexts to uint32
func (dec *Decryptor) DecryptUint32(cts [32]*Ciphertext) uint32 {
var v uint32
for i := 0; i < 32; i++ {
if dec.Decrypt(cts[i]) {
v |= 1 << i
}
}
return v
}
// DecryptUint64 decrypts 64 ciphertexts to uint64
func (dec *Decryptor) DecryptUint64(cts [64]*Ciphertext) uint64 {
var v uint64
for i := 0; i < 64; i++ {
if dec.Decrypt(cts[i]) {
v |= 1 << i
}
}
return v
}
// DecryptUint256 decrypts 256 ciphertexts to 4 uint64s
func (dec *Decryptor) DecryptUint256(cts [256]*Ciphertext) [4]uint64 {
var v [4]uint64
for w := 0; w < 4; w++ {
for i := 0; i < 64; i++ {
if dec.Decrypt(cts[w*64+i]) {
v[w] |= 1 << i
}
}
}
return v
}
-47
View File
@@ -1,47 +0,0 @@
import { source } from '@/lib/source'
import type { Metadata } from 'next'
import { DocsPage, DocsBody, DocsTitle, DocsDescription } from 'fumadocs-ui/page'
import { notFound } from 'next/navigation'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import rehypeHighlight from 'rehype-highlight'
import 'highlight.js/styles/github-dark.css'
export default async function Page(props: {
params: Promise<{ slug?: string[] }>
}) {
const params = await props.params
const page = source.getPage(params.slug)
if (!page) notFound()
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<div className="prose prose-neutral dark:prose-invert max-w-none">
<ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeHighlight]}>
{page.data.content}
</ReactMarkdown>
</div>
</DocsBody>
</DocsPage>
)
}
export async function generateStaticParams() {
return source.generateParams()
}
export async function generateMetadata(props: {
params: Promise<{ slug?: string[] }>
}): Promise<Metadata> {
const params = await props.params
const page = source.getPage(params.slug)
if (!page) notFound()
return {
title: page.data.title,
description: page.data.description,
}
}
-109
View File
@@ -1,109 +0,0 @@
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
import type { ReactNode } from 'react'
import { ExternalLink, Github } from 'lucide-react'
import { Logo, LogoWithText } from '@/components/logo'
import { source } from '@/lib/source'
function DiscordIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/>
</svg>
)
}
function XIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 24 24" fill="currentColor">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
</svg>
)
}
const DOCS_CONFIG = {
name: 'Lux TFHE',
github: 'https://github.com/luxfi/fhe',
socials: {
website: 'https://lux.network',
discord: 'https://discord.gg/luxfi',
twitter: 'https://x.com/luxdefi',
},
footerLinks: [
{
text: 'View on GitHub',
url: 'https://github.com/luxfi/fhe',
icon: 'github',
},
{
text: 'Lux Network Docs',
url: 'https://docs.lux.network',
icon: 'external',
},
],
}
export default function Layout({ children }: { children: ReactNode }) {
return (
<DocsLayout
tree={source.pageTree}
nav={{
title: <LogoWithText size={24} name={DOCS_CONFIG.name} />,
}}
sidebar={{
defaultOpenLevel: 1,
footer: (
<div className="flex flex-col gap-3 text-xs">
<div className="flex items-center gap-3">
<a
href={DOCS_CONFIG.socials.website}
target="_blank"
rel="noopener noreferrer"
className="text-fd-muted-foreground hover:text-fd-foreground transition-colors"
title="Lux Network"
>
<Logo size={20} />
</a>
<a
href={DOCS_CONFIG.socials.discord}
target="_blank"
rel="noopener noreferrer"
className="text-fd-muted-foreground hover:text-fd-foreground transition-colors"
title="Discord"
>
<DiscordIcon className="size-5" />
</a>
<a
href={DOCS_CONFIG.socials.twitter}
target="_blank"
rel="noopener noreferrer"
className="text-fd-muted-foreground hover:text-fd-foreground transition-colors"
title="X"
>
<XIcon className="size-5" />
</a>
</div>
{DOCS_CONFIG.footerLinks.map((link, index) => (
<a
key={index}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-fd-muted-foreground hover:text-fd-foreground transition-colors"
>
{link.icon === 'github' ? (
<Github className="size-4" />
) : (
<ExternalLink className="size-4" />
)}
{link.text}
</a>
))}
</div>
),
}}
>
{children}
</DocsLayout>
)
}
-222
View File
@@ -1,222 +0,0 @@
/**
* Lux TFHE Documentation Theme
* Matches Lux Network documentation styling
*/
@import 'tailwindcss';
@custom-variant dark (&:is(.dark *));
/* Light mode - clean minimal */
:root {
--background: 0 0% 100%;
--foreground: 0 0% 9%;
--card: 0 0% 100%;
--card-foreground: 0 0% 9%;
--popover: 0 0% 100%;
--popover-foreground: 0 0% 9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 100%;
--secondary: 0 0% 96%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96%;
--muted-foreground: 0 0% 45%;
--accent: 0 0% 96%;
--accent-foreground: 0 0% 9%;
--border: 0 0% 90%;
--input: 0 0% 90%;
--ring: 0 0% 64%;
/* Fumadocs color overrides */
--color-fd-background: hsl(0, 0%, 100%);
--color-fd-foreground: hsl(0, 0%, 9%);
--color-fd-muted: hsl(0, 0%, 96%);
--color-fd-muted-foreground: hsl(0, 0%, 45%);
--color-fd-popover: hsl(0, 0%, 100%);
--color-fd-popover-foreground: hsl(0, 0%, 9%);
--color-fd-card: hsl(0, 0%, 100%);
--color-fd-card-foreground: hsl(0, 0%, 9%);
--color-fd-border: hsl(0, 0%, 90%);
--color-fd-primary: hsl(0, 0%, 9%);
--color-fd-primary-foreground: hsl(0, 0%, 100%);
--color-fd-secondary: hsl(0, 0%, 96%);
--color-fd-secondary-foreground: hsl(0, 0%, 9%);
--color-fd-accent: hsl(0, 0%, 96%);
--color-fd-accent-foreground: hsl(0, 0%, 9%);
--color-fd-ring: hsl(0, 0%, 64%);
}
/* Dark mode - true black */
.dark {
--background: 0 0% 0%;
--foreground: 0 0% 98%;
--card: 0 0% 4%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 4%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 4%;
--secondary: 0 0% 10%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 8%;
--muted-foreground: 0 0% 55%;
--accent: 0 0% 12%;
--accent-foreground: 0 0% 98%;
--border: 0 0% 15%;
--input: 0 0% 15%;
--ring: 0 0% 36%;
/* Fumadocs dark overrides */
--color-fd-background: hsl(0, 0%, 0%);
--color-fd-foreground: hsl(0, 0%, 98%);
--color-fd-muted: hsl(0, 0%, 8%);
--color-fd-muted-foreground: hsl(0, 0%, 55%);
--color-fd-popover: hsl(0, 0%, 4%);
--color-fd-popover-foreground: hsl(0, 0%, 98%);
--color-fd-card: hsl(0, 0%, 4%);
--color-fd-card-foreground: hsl(0, 0%, 98%);
--color-fd-border: hsl(0, 0%, 15%);
--color-fd-primary: hsl(0, 0%, 98%);
--color-fd-primary-foreground: hsl(0, 0%, 4%);
--color-fd-secondary: hsl(0, 0%, 10%);
--color-fd-secondary-foreground: hsl(0, 0%, 98%);
--color-fd-accent: hsl(0, 0%, 12%);
--color-fd-accent-foreground: hsl(0, 0%, 98%);
--color-fd-ring: hsl(0, 0%, 36%);
}
/* Base styles */
* {
border-color: hsl(var(--border));
}
html {
scroll-behavior: smooth;
-webkit-font-smoothing: antialiased;
}
body {
font-synthesis-weight: none;
text-rendering: optimizeLegibility;
}
/* Selection */
::selection {
background: rgba(0, 0, 0, 0.15);
}
.dark ::selection {
background: rgba(255, 255, 255, 0.20);
}
/* Code blocks - dark theme */
pre {
background: #0d0d0d !important;
color: #e8e8e8;
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 0.625rem;
padding: 1rem;
overflow-x: auto;
line-height: 1.5;
font-variant-ligatures: none;
}
pre code {
background: transparent !important;
border: none !important;
padding: 0 !important;
font-size: inherit;
color: inherit;
}
/* Inline code */
:not(pre) > code {
background: hsl(var(--muted));
border-radius: 0.375rem;
padding: 0.2em 0.45em;
font-size: 0.875em;
}
/* Remove typography plugin backticks */
code::before,
code::after {
content: none !important;
}
/* Tables */
th {
background: hsl(var(--muted) / 0.4);
}
tr:hover td {
background: hsl(var(--muted) / 0.2);
}
/* Blockquotes */
blockquote {
border-left: 3px solid hsl(var(--primary) / 0.3);
background: hsl(var(--muted) / 0.3);
border-radius: 0 0.5rem 0.5rem 0;
}
/* Typography improvements */
h2 {
padding-bottom: 0.75rem;
border-bottom: 1px solid hsl(var(--border) / 0.4);
}
/* Sidebar refinements */
aside[role="complementary"] {
border-right: 1px solid hsl(var(--border) / 0.5);
}
/* Hide mobile subnav header on desktop */
@media (min-width: 768px) {
header#nd-subnav {
display: none !important;
}
}
/* TOC refinements */
nav[aria-label="Table of Contents"] {
border-left: 1px solid hsl(var(--border) / 0.3);
}
/* Sidebar footer - social icons left, theme toggle right */
aside .border-t.p-4.pt-2 {
flex-direction: row !important;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem;
}
/* Theme toggle div pushed to right */
aside .border-t.p-4.pt-2 > div:first-child {
flex-shrink: 0;
order: 1;
margin-left: auto;
}
/* Social icons come first (left side) */
aside .border-t.p-4.pt-2 > div:last-child > div:first-child {
order: 0;
}
/* Our footer content - social icons inline, links below */
aside .border-t.p-4.pt-2 > div:last-child {
display: contents;
}
/* Social icons row inline with theme toggle */
aside .border-t.p-4.pt-2 > div:last-child > div:first-child {
display: flex;
align-items: center;
gap: 0.75rem;
}
/* Text links on new row, full width, after theme toggle */
aside .border-t.p-4.pt-2 > div:last-child > a {
width: 100%;
flex-basis: 100%;
order: 2;
}
-97
View File
@@ -1,97 +0,0 @@
import type { ReactNode } from 'react'
import { RootProvider } from 'fumadocs-ui/provider'
import { Geist, Geist_Mono } from 'next/font/google'
import 'fumadocs-ui/style.css'
import './globals.css'
const geist = Geist({
subsets: ['latin'],
variable: '--font-geist',
display: 'swap',
})
const geistMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-geist-mono',
display: 'swap',
})
// ============================================================================
// CONFIGURE YOUR DOCS SITE HERE
// ============================================================================
const SITE_CONFIG = {
name: 'Lux TFHE',
description: 'Threshold Fully Homomorphic Encryption for the Lux Network. Compute on encrypted data without ever decrypting it. Multi-GPU acceleration with Metal, CUDA, and CPU backends.',
url: 'https://tfhe.lux.network',
keywords: ['TFHE', 'FHE', 'homomorphic encryption', 'threshold encryption', 'Lux Network', 'GPU', 'CUDA', 'Metal', 'MLX', 'privacy', 'confidential computing'],
}
export const metadata = {
title: {
default: SITE_CONFIG.name,
template: `%s | ${SITE_CONFIG.name}`,
},
description: SITE_CONFIG.description,
keywords: SITE_CONFIG.keywords,
authors: [{ name: 'Lux Network' }],
metadataBase: new URL(SITE_CONFIG.url),
icons: {
icon: '/favicon.svg',
apple: '/favicon.svg',
},
openGraph: {
title: SITE_CONFIG.name,
description: SITE_CONFIG.description,
type: 'website',
siteName: SITE_CONFIG.name,
images: [
{
url: '/og.png',
width: 1200,
height: 630,
alt: SITE_CONFIG.name,
},
],
},
twitter: {
card: 'summary_large_image',
title: SITE_CONFIG.name,
description: SITE_CONFIG.description,
images: ['/og.png'],
},
}
export default function RootLayout({
children
}: {
children: ReactNode
}) {
return (
<html lang="en" className={`${geist.variable} ${geistMono.variable}`} suppressHydrationWarning>
<head>
{/* Prevent flash - respect system preference */}
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
document.documentElement.classList.add('dark');
})();
`,
}}
/>
</head>
<body className="min-h-screen bg-background font-sans antialiased">
<RootProvider
theme={{
enabled: true,
defaultTheme: 'dark',
}}
>
<div className="relative flex min-h-screen flex-col">
{children}
</div>
</RootProvider>
</body>
</html>
)
}
-5
View File
@@ -1,5 +0,0 @@
import { redirect } from 'next/navigation'
export default function HomePage() {
redirect('/docs')
}
-37
View File
@@ -1,37 +0,0 @@
'use client'
import { getMenuBarSVG } from '@luxfi/logo'
interface LogoProps {
size?: number
className?: string
}
export function Logo({ size = 24, className = '' }: LogoProps) {
const svg = getMenuBarSVG()
return (
<div
className={`logo-container inline-block ${className}`}
style={{ width: size, height: size }}
dangerouslySetInnerHTML={{ __html: svg }}
/>
)
}
interface LogoWithTextProps {
size?: number
name?: string
}
export function LogoWithText({ size = 24, name = 'Docs' }: LogoWithTextProps) {
return (
<div className="flex items-center gap-2 group">
<Logo
size={size}
className="transition-transform duration-200 group-hover:scale-110"
/>
<span className="font-bold text-lg">{name}</span>
</div>
)
}
-168
View File
@@ -1,168 +0,0 @@
---
title: API Reference
description: Complete API documentation for Lux FHE
---
# API Reference
## Integer Types
| Type | Bits | Use Case |
|------|------|----------|
| `FheBool` | 1 | Boolean flags, comparison results |
| `FheUint4` | 4 | Nibbles, small counters |
| `FheUint8` | 8 | Bytes, small integers |
| `FheUint16` | 16 | Short integers |
| `FheUint32` | 32 | Standard integers |
| `FheUint64` | 64 | Large integers |
| `FheUint128` | 128 | UUIDs, very large values |
| `FheUint160` | 160 | Ethereum addresses |
| `FheUint256` | 256 | EVM word size |
## Key Types
### SecretKey
The private key used for decryption. **Never share this key.**
### PublicKey
The public key used for encryption. Can be freely shared with users.
### BootstrapKey
The key used for homomorphic operations. Share with computation servers.
## Encryptors
### BitwiseEncryptor (Secret Key)
```go
enc := tfhe.NewBitwiseEncryptor(params, sk)
ct := enc.EncryptUint64(value, tfhe.FheUint8)
```
### BitwisePublicEncryptor (Public Key)
```go
pubEnc := tfhe.NewBitwisePublicEncryptor(params, pk)
ct := pubEnc.EncryptUint64(value, tfhe.FheUint8)
```
## Decryptor
```go
dec := tfhe.NewBitwiseDecryptor(params, sk)
value := dec.DecryptUint64(ct)
```
## Evaluator
### Arithmetic Operations
```go
eval := tfhe.NewBitwiseEvaluator(params, bsk, sk)
// Addition
sum, err := eval.Add(a, b)
// Subtraction
diff, err := eval.Sub(a, b)
// Scalar addition (add plaintext constant)
result, err := eval.ScalarAdd(a, 5)
// Negation
neg, err := eval.Neg(a)
```
### Comparison Operations
```go
// All comparisons return a single encrypted bit (FheBool)
eq, err := eval.Eq(a, b) // Equal
lt, err := eval.Lt(a, b) // Less than
le, err := eval.Le(a, b) // Less than or equal
gt, err := eval.Gt(a, b) // Greater than
ge, err := eval.Ge(a, b) // Greater than or equal
// Min/Max return the minimum/maximum of two values
min, err := eval.Min(a, b)
max, err := eval.Max(a, b)
```
### Bitwise Operations
```go
and, err := eval.And(a, b) // Bitwise AND
or, err := eval.Or(a, b) // Bitwise OR
xor, err := eval.Xor(a, b) // Bitwise XOR
not, err := eval.Not(a) // Bitwise NOT
```
### Shift Operations
```go
left, err := eval.Shl(a, 2) // Shift left by 2
right, err := eval.Shr(a, 2) // Shift right by 2
```
### Selection
```go
// Select based on encrypted condition (MUX)
// Returns a if cond is true, b otherwise
result, err := eval.Select(cond, a, b)
```
### Type Conversion
```go
// Convert from one type to another
result, err := eval.CastTo(value, tfhe.FheUint16)
```
## Boolean Gates
For low-level operations on individual encrypted bits:
```go
boolEval := tfhe.NewEvaluator(params, bsk)
and := boolEval.And(a, b)
or := boolEval.Or(a, b)
xor := boolEval.Xor(a, b)
not := boolEval.Not(a)
nand := boolEval.Nand(a, b)
nor := boolEval.Nor(a, b)
xnor := boolEval.Xnor(a, b)
mux := boolEval.Mux(cond, a, b)
```
## Serialization
```go
// Serialize ciphertext
bytes, err := ct.MarshalBinary()
// Deserialize ciphertext
ct := new(tfhe.BitCiphertext)
err := ct.UnmarshalBinary(bytes)
// Keys can also be serialized
skBytes, _ := sk.MarshalBinary()
pkBytes, _ := pk.MarshalBinary()
bskBytes, _ := bsk.MarshalBinary()
```
## Random Number Generation
```go
// Secret key RNG (for trusted environments)
rng := tfhe.NewFheRNG(params, sk, seed)
randomCt := rng.RandomUint(tfhe.FheUint8)
// Public key RNG (for untrusted environments)
pubRng := tfhe.NewFheRNGPublic(params, pk, seed)
randomCt := pubRng.RandomUint(tfhe.FheUint8)
```
-112
View File
@@ -1,112 +0,0 @@
---
title: Benchmarks
description: Performance characteristics of Lux FHE
---
# Benchmarks
All benchmarks run on Apple M1 Max (ARM64).
## Summary Comparison
| Operation | Pure Go | OpenFHE (CGO) | Winner |
|-----------|---------|---------------|--------|
| SecretKey Gen | 41.7 µs | 14.4 µs | CGO 2.9x |
| BootstrapKey Gen | 131.9 ms | 2413 ms | **Go 18x** |
| Encrypt Bit | 20.8 µs | 27.7 µs | Go 1.3x |
| Decrypt Bit | 4.5 µs | 1.4 µs | CGO 3.2x |
| NOT | 1.2 µs | 1.4 µs | ~Same |
| AND | 51.3 ms | 56.2 ms | **Go 1.10x** |
| OR | 52.3 ms | 56.4 ms | **Go 1.08x** |
| XOR | 51.2 ms | 56.3 ms | **Go 1.10x** |
| NAND | 52.0 ms | 56.4 ms | **Go 1.08x** |
| NOR | 52.2 ms | 56.3 ms | **Go 1.08x** |
| XNOR | 51.0 ms | 57.6 ms | **Go 1.13x** |
**Key Findings:**
- Pure Go bootstrap key gen is **18x faster** than OpenFHE
- Pure Go is faster for **ALL gates** (~51ms vs ~56ms)
- XOR/XNOR optimized to use single bootstrap
## Boolean Gate Operations
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| NOT | 1.2 µs | 8.9 KB | 11 |
| AND | 51.3 ms | 1.2 MB | 38K |
| OR | 52.3 ms | 1.2 MB | 38K |
| XOR | 51.2 ms | 1.2 MB | 38K |
| NAND | 52.0 ms | 1.2 MB | 38K |
| NOR | 52.2 ms | 1.2 MB | 38K |
| XNOR | 51.0 ms | 1.2 MB | 38K |
| MUX | 158.4 ms | 3.6 MB | 114K |
## Multi-Input Gates
| Operation | Time | Memory | Notes |
|-----------|------|--------|-------|
| AND3 | 117.2 ms | 2.4 MB | 2 bootstraps |
| OR3 | 118.7 ms | 2.4 MB | 2 bootstraps |
| MAJORITY | 58.6 ms | 1.2 MB | **1 bootstrap** |
## Integer Encryption/Decryption
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Encrypt 8-bit | 166.8 µs | 128 KB | 234 |
| Encrypt 16-bit | 326.6 µs | 256 KB | 466 |
| Encrypt 32-bit | 663.5 µs | 512 KB | 930 |
| Decrypt 8-bit | 36.5 µs | 37.9 KB | 64 |
| Decrypt 16-bit | 74.0 µs | 75.8 KB | 128 |
## Integer Arithmetic (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Add | 3.50 s | 81.2 MB | 2.6M |
| Sub | 5.20 s | 115.1 MB | 3.6M |
| ScalarAdd | 1.61 s | 36.2 MB | 1.1M |
## Integer Comparisons (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| Eq | 1.74 s | 37.3 MB | 1.2M |
| Lt | 2.91 s | 64.0 MB | 2.0M |
| Le | 4.52 s | 102.8 MB | 3.2M |
| Gt | 2.78 s | 64.1 MB | 2.0M |
| Min | 4.00 s | 93.1 MB | 2.9M |
| Max | 4.01 s | 93.0 MB | 2.9M |
## Bitwise Operations (8-bit)
| Operation | Time | Memory | Allocs |
|-----------|------|--------|--------|
| AND | 420.5 ms | 9.7 MB | 306K |
| OR | 429.2 ms | 9.6 MB | 304K |
| XOR | 1.45 s | 29.0 MB | 916K |
| NOT | 10.5 µs | 71.0 KB | 90 |
| Shl | 9.9 µs | 35.4 KB | 42 |
| Shr | 9.6 µs | 35.4 KB | 42 |
## Running Benchmarks
```bash
# All benchmarks
go test -bench=. -benchmem -run=^$ .
# Only lattice benchmarks
go test -bench=BenchmarkLattice -benchmem -run=^$ .
# With memory profiling
go test -bench=BenchmarkLatticeAdd8 -benchmem -memprofile=mem.prof -run=^$ .
```
## Recommendations
| Use Case | Recommended Backend |
|----------|---------------------|
| Startup-sensitive (key gen) | Pure Go |
| All boolean circuits | Pure Go (faster) |
| No C++ dependencies needed | Pure Go |
| Maximum integer performance | OpenFHE (GPU future) |
-243
View File
@@ -1,243 +0,0 @@
---
title: GPU Acceleration
description: Multi-GPU FHE acceleration with Metal (macOS) and CUDA (Linux/Windows)
---
# GPU Acceleration
Lux FHE supports massively parallel bootstrapping on GPUs, providing 10-100x speedup for batch operations.
## Supported Backends
| Backend | Platform | Hardware | Status |
|---------|----------|----------|--------|
| Metal/MLX | macOS 13+ | Apple Silicon (M1/M2/M3) | ✅ Production |
| CUDA | Linux/Windows | NVIDIA GPU (Compute 7.0+) | 🚧 In Development |
| CPU | Any | Any | ✅ Fallback |
## macOS Setup (Metal/MLX)
Metal acceleration works out of the box on Apple Silicon Macs:
```go
import "github.com/luxfi/fhe/gpu"
// Auto-detect Metal GPU
cfg := gpu.Config{
Backends: []string{"metal", "cpu"}, // Fallback to CPU if Metal unavailable
}
engine, err := gpu.New(cfg)
if err != nil {
log.Fatal(err)
}
defer engine.Close()
// Check what backend was selected
info := engine.Info()
fmt.Printf("Using: %s (%s)\n", info.Backend, info.DeviceName)
// Output: Using: metal (Apple M1 Max)
```
## Linux/Windows Setup (CUDA)
CUDA acceleration requires the NVIDIA CUDA Toolkit:
```bash
# Install CUDA Toolkit (Ubuntu/Debian)
sudo apt install nvidia-cuda-toolkit
# Or download from NVIDIA
# https://developer.nvidia.com/cuda-downloads
```
```go
cfg := gpu.Config{
Backends: []string{"cuda", "cpu"},
}
engine, _ := gpu.New(cfg)
```
## Configuration Options
```go
type Config struct {
// Backends in priority order
// Options: "metal", "cuda", "cpu"
Backends []string
// Maximum ciphertexts per batch
// Larger = more parallelism, more memory
MaxBatchSize int // Default: 1024
// GPU memory limit in bytes
// 0 = use all available
MemoryLimit int64 // Default: 0
// Number of GPU streams (CUDA only)
NumStreams int // Default: 4
// Enable async execution
Async bool // Default: true
}
```
## Batch Operations
The GPU engine excels at batch operations:
```go
// Single operation (minimal speedup)
result, _ := engine.Bootstrap(ct, bsk)
// Batch operation (10-100x speedup)
results, _ := engine.BatchBootstrap(ciphertexts, bsk)
// Boolean gates on encrypted integers
sumCts, _ := engine.BatchAdd(aInts, bInts, bsk)
```
## Performance Characteristics
### Batch Size vs Throughput
| Batch Size | M1 Max (Metal) | RTX 4090 (CUDA) |
|------------|----------------|-----------------|
| 1 | ~50 ms | ~40 ms |
| 10 | ~60 ms | ~45 ms |
| 100 | ~150 ms | ~100 ms |
| 1000 | ~500 ms | ~300 ms |
| 10000 | ~4 s | ~2.5 s |
*Throughput increases dramatically with batch size.*
### Memory Requirements
| Batch Size | GPU Memory |
|------------|------------|
| 100 | ~500 MB |
| 1000 | ~2 GB |
| 10000 | ~8 GB |
## Multi-GPU Support
For systems with multiple GPUs:
```go
cfg := gpu.Config{
Backends: []string{"cuda"},
DeviceIndex: 0, // GPU 0
}
engine0, _ := gpu.New(cfg)
cfg.DeviceIndex = 1 // GPU 1
engine1, _ := gpu.New(cfg)
// Distribute work across GPUs
go engine0.BatchBootstrap(batch1, bsk)
go engine1.BatchBootstrap(batch2, bsk)
```
## Async Execution
For maximum throughput with streaming data:
```go
cfg := gpu.Config{
Backends: []string{"metal"},
Async: true,
}
engine, _ := gpu.New(cfg)
// Submit work without blocking
future1 := engine.BatchBootstrapAsync(batch1, bsk)
future2 := engine.BatchBootstrapAsync(batch2, bsk)
// Do other work...
// Collect results
results1, _ := future1.Wait()
results2, _ := future2.Wait()
```
## Error Handling
```go
engine, err := gpu.New(cfg)
if err != nil {
switch {
case errors.Is(err, gpu.ErrNotSupported):
// Platform doesn't support any GPU backend
// Fall back to pure Go implementation
case errors.Is(err, gpu.ErrOutOfMemory):
// Not enough GPU memory
// Reduce batch size or memory limit
default:
log.Fatal(err)
}
}
```
## Benchmarking Your System
```bash
# Run GPU benchmarks
go test -bench=BenchmarkGPU -benchmem github.com/luxfi/fhe/gpu
# Compare with CPU
go test -bench=BenchmarkLattice -benchmem github.com/luxfi/fhe
```
## Platform-Specific Notes
### macOS (Metal/MLX)
- Requires macOS 13.0+ (Ventura or later)
- Works on Apple Silicon (M1, M2, M3 series)
- Intel Macs not supported (falls back to CPU)
- Uses MLX framework for optimal Metal performance
### Linux (CUDA)
- Requires CUDA Toolkit 11.0+
- NVIDIA GPU with Compute Capability 7.0+ (Volta or newer)
- Tested on: RTX 3090, RTX 4090, A100, H100
### Windows (CUDA)
- Same requirements as Linux
- CUDA Toolkit for Windows
- WSL2 also works with Linux CUDA backend
## Troubleshooting
### Metal not detected on macOS
```bash
# Check Metal support
system_profiler SPDisplaysDataType | grep Metal
```
### CUDA not detected on Linux
```bash
# Check CUDA installation
nvcc --version
nvidia-smi
# Check Go can find CUDA
export CGO_CFLAGS="-I/usr/local/cuda/include"
export CGO_LDFLAGS="-L/usr/local/cuda/lib64"
```
### Out of memory errors
Reduce batch size or set a memory limit:
```go
cfg := gpu.Config{
MaxBatchSize: 256, // Smaller batches
MemoryLimit: 2 << 30, // 2GB limit
}
```
-127
View File
@@ -1,127 +0,0 @@
---
title: Lux TFHE
description: Threshold Fully Homomorphic Encryption for Lux Network with Multi-GPU acceleration
---
Compute on encrypted data without ever decrypting it. Built for the Lux Network with multi-GPU acceleration.
## Backends
| Backend | Platform | Performance | Use Case |
|---------|----------|-------------|----------|
| **Pure Go** | Any | Baseline | Portability, no dependencies |
| **Metal/MLX** | macOS | 10-100x | Apple Silicon acceleration |
| **CUDA** | Linux/Windows | 10-100x | NVIDIA GPU acceleration |
| **CGO/OpenFHE** | Any | ~1x | Interoperability |
## Features
- **Multi-GPU Acceleration**: Massively parallel bootstrapping on Metal (macOS) and CUDA (Linux/Windows)
- **Lux Network Native**: Designed for confidential smart contracts and threshold decryption
- **Pure Go Fallback**: Zero dependencies option - compiles anywhere Go runs
- **Patent-Safe**: Classic boolean circuit approach, no patented techniques
- **Full Integer Support**: FheUint4 through FheUint256 (including Ethereum addresses)
- **Blockchain Ready**: Public key encryption, deterministic RNG, serialization
## Quick Start
```bash
go get github.com/luxfi/fhe
```
```go
package main
import (
"fmt"
"github.com/luxfi/fhe"
)
func main() {
// Setup
params, _ := tfhe.NewParametersFromLiteral(tfhe.PN10QP27)
kg := tfhe.NewKeyGenerator(params)
sk, pk := kg.GenKeyPair()
bsk := kg.GenBootstrapKey(sk)
// Encrypt with public key
pubEnc := tfhe.NewBitwisePublicEncryptor(params, pk)
ctA := pubEnc.EncryptUint64(5, tfhe.FheUint8)
ctB := pubEnc.EncryptUint64(3, tfhe.FheUint8)
// Compute on encrypted data
eval := tfhe.NewBitwiseEvaluator(params, bsk, sk)
ctSum, _ := eval.Add(ctA, ctB)
// Decrypt result
dec := tfhe.NewBitwiseDecryptor(params, sk)
result := dec.DecryptUint64(ctSum)
fmt.Println("5 + 3 =", result) // 8
}
```
## GPU Acceleration (macOS)
```go
import "github.com/luxfi/fhe/gpu"
// Configure GPU engine
cfg := gpu.Config{
Backends: []string{"metal", "cpu"},
MaxBatchSize: 1024,
MemoryLimit: 4 * 1024 * 1024 * 1024, // 4GB
}
engine, _ := gpu.New(cfg)
defer engine.Close()
// Batch operations execute in parallel on GPU
results, _ := engine.BatchBootstrap(ciphertexts, bsk)
```
## Performance (Apple M1 Max)
| Operation | Pure Go | GPU | Speedup |
|-----------|---------|-----|---------|
| Bootstrap Key Gen | 132 ms | 132 ms | 1x |
| Boolean Gate (AND) | 51 ms | ~5 ms | **10x** |
| 8-bit Integer Add | 3.5 s | ~350 ms | **10x** |
| Batch 1000 ANDs | 51 s | ~500 ms | **100x** |
*GPU acceleration provides massive speedup for batch operations.*
## Documentation
- [Overview](/docs/overview) - What is TFHE and how does it work?
- [GPU Acceleration](/docs/gpu) - Multi-GPU setup for Metal and CUDA
- [API Reference](/docs/api) - Complete API documentation
- [Benchmarks](/docs/benchmarks) - Detailed performance characteristics
- [Security](/docs/security) - Security model and guarantees
- [License](/docs/license) - Licensing information
## Architecture
```
tfhe/
├── fhe.go # Core FHE types and parameters
├── keygen.go # Key generation (secret, public, bootstrap)
├── encryptor.go # Encryption with secret/public keys
├── decryptor.go # Decryption
├── evaluator.go # Homomorphic operations
├── integer.go # Integer encryption/decryption
├── bitwise.go # Boolean circuit operations
├── gpu/ # Multi-GPU acceleration
│ ├── engine.go # Metal/MLX backend (macOS)
│ └── cuda/ # CUDA backend (Linux/Windows)
└── server/ # Threshold decryption server
```
## License
BSD-3-Clause + Patent Rights Reserved
- **Lux Network**: Free to use on Lux mainnet/testnets
- **Research/Academic**: Free for non-commercial use
- **Commercial**: License required for other networks
Contact: [email protected]
-68
View File
@@ -1,68 +0,0 @@
---
title: License
description: Licensing information for Lux FHE
---
# License
## BSD 3-Clause License + Patent Rights Reserved
Copyright (c) 2025 Lux Partners Limited. All rights reserved.
## Software License
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice
2. Redistributions in binary form must reproduce the above copyright notice
3. Neither the name of Lux Partners Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission
## Patent Rights Reserved
All patent rights relating to this software and its implementation techniques are expressly reserved by Lux Partners Limited. This license does NOT grant any patent license, express or implied.
## Usage Terms
### Lux Network Exception (Free)
Use of this software on the Lux Network mainnet and its official testnets is permitted without additional licensing fees. This includes:
- Smart contracts and dApps deployed on Lux Network
- Validators and nodes operating on Lux Network
- Integration with Lux Network infrastructure
- fhEVM operations on Lux Network chains
### Research & Academic Use (Free)
Non-commercial use for research, education, and academic purposes is permitted without additional licensing, subject to citation requirements.
### Commercial License Required
Any commercial use of this software outside of the Lux Network requires a separate commercial license from Lux Partners Limited. This includes:
- Use on other blockchain networks
- Use in commercial products or services
- SaaS offerings incorporating this technology
- Enterprise deployments
- Any for-profit use outside Lux Network
## Contact
For commercial licensing inquiries: [[email protected]](mailto:[email protected])
## Implementation Notice
This is an **ORIGINAL implementation** of FHE written from scratch in Go, based on published academic research:
- Built entirely on [github.com/luxfi/lattice](https://github.com/luxfi/lattice) (our own cryptographic primitives)
- Implements algorithms from peer-reviewed publications
- Contains novel optimizations developed independently
### Referenced Academic Works
- Chillotti et al. "FHE: Fast Fully Homomorphic Encryption Over the Torus" (Journal of Cryptology, 2020)
- Ducas & Micciancio "FHEW: Bootstrapping Homomorphic Encryption in Less Than a Second" (EUROCRYPT 2015)
## Disclaimer
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL LUX PARTNERS LIMITED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-15
View File
@@ -1,15 +0,0 @@
{
"title": "Documentation",
"pages": [
"index",
"overview",
"---SDK---",
"sdk",
"---Reference---",
"gpu",
"api",
"benchmarks",
"security",
"license"
]
}
-83
View File
@@ -1,83 +0,0 @@
---
title: Overview
description: What is FHE and how does it work?
---
# Overview
## What is FHE?
**Threshold Fully Homomorphic Encryption (FHE)** is a cryptographic technique that allows computation on encrypted data without decryption. The result of the computation is also encrypted, and only the holder of the secret key can decrypt it.
This enables privacy-preserving computation where:
- Users encrypt their data with a public key
- Servers perform computations on encrypted data
- Only the user can decrypt the final result
## How It Works
### 1. Key Generation
```go
params, _ := tfhe.NewParametersFromLiteral(tfhe.PN10QP27)
kg := tfhe.NewKeyGenerator(params)
sk, pk := kg.GenKeyPair() // Secret key (private), Public key (shareable)
bsk := kg.GenBootstrapKey(sk) // Bootstrap key (for server operations)
```
### 2. Encryption (User Side)
Users encrypt their data using the **public key** - they never need the secret key:
```go
pubEnc := tfhe.NewBitwisePublicEncryptor(params, pk)
encryptedValue := pubEnc.EncryptUint64(42, tfhe.FheUint8)
```
### 3. Computation (Server Side)
The server performs operations on encrypted data using the **bootstrap key**:
```go
eval := tfhe.NewBitwiseEvaluator(params, bsk, sk)
result, _ := eval.Add(encA, encB) // Addition on encrypted data
```
### 4. Decryption (User Side)
Only the holder of the secret key can decrypt:
```go
dec := tfhe.NewBitwiseDecryptor(params, sk)
plaintext := dec.DecryptUint64(result)
```
## Boolean Circuit Approach
Lux FHE uses a **boolean circuit approach** for integer operations:
1. Each integer is represented as a vector of encrypted bits
2. Operations are built from basic boolean gates (AND, OR, XOR, NOT)
3. Each boolean gate requires a "bootstrapping" operation to reduce noise
This approach is:
- **Patent-safe**: Uses pre-2020 techniques with no patented LUT methods
- **Flexible**: Supports arbitrary bit widths (4-256 bits)
- **Predictable**: Performance scales linearly with bit width
## Security
FHE security is based on the **Learning With Errors (LWE)** problem, which is believed to be resistant to both classical and quantum computers.
Key security features:
- 128-bit security level
- Semantic security (identical plaintexts have different ciphertexts)
- IND-CPA secure encryption
## Use Cases
- **Confidential Smart Contracts**: Execute logic without revealing inputs
- **Privacy-Preserving DeFi**: Trade without exposing positions
- **Encrypted Voting**: Vote without revealing choices
- **Secure Auctions**: Bid without revealing amounts
- **Private Analytics**: Compute statistics on encrypted data
-238
View File
@@ -1,238 +0,0 @@
---
title: C/C++ SDK
description: Native C/C++ SDK for LuxFHE
---
# C/C++ SDK
The C SDK provides native bindings with full C++ compatibility via `extern "C"`.
## Installation
### macOS / Linux
```bash
# Build from source
cd tfhe/c
mkdir build && cd build
cmake ..
make
sudo make install
```
### Using pkg-config
```bash
# After installation
pkg-config --cflags --libs luxfhe
```
### CMake Integration
```cmake
find_package(luxfhe REQUIRED)
target_link_libraries(myapp PRIVATE luxfhe::luxfhe)
```
## Quick Start (C)
```c
#include <stdio.h>
#include <luxfhe.h>
int main() {
// Create context
LuxFHE_Context ctx = NULL;
luxfhe_context_new(LUXFHE_PARAMS_PN10QP27, &ctx);
// Generate keys
LuxFHE_SecretKey sk = NULL;
LuxFHE_PublicKey pk = NULL;
LuxFHE_BootstrapKey bsk = NULL;
luxfhe_keygen_secret(ctx, &sk);
luxfhe_keygen_public(ctx, sk, &pk);
luxfhe_keygen_bootstrap(ctx, sk, &bsk);
// Create encryptor/decryptor/evaluator
LuxFHE_Encryptor enc = NULL;
LuxFHE_Decryptor dec = NULL;
LuxFHE_Evaluator eval = NULL;
luxfhe_encryptor_new_pk(ctx, pk, &enc);
luxfhe_decryptor_new(ctx, sk, &dec);
luxfhe_evaluator_new(ctx, bsk, sk, &eval);
// Encrypt
LuxFHE_Ciphertext ct_true = NULL;
LuxFHE_Ciphertext ct_false = NULL;
luxfhe_encrypt_bool(enc, true, &ct_true);
luxfhe_encrypt_bool(enc, false, &ct_false);
// Compute AND gate
LuxFHE_Ciphertext ct_result = NULL;
luxfhe_and(eval, ct_true, ct_false, &ct_result);
// Decrypt
bool result;
luxfhe_decrypt_bool(dec, ct_result, &result);
printf("true AND false = %s\n", result ? "true" : "false");
// Cleanup
luxfhe_ciphertext_free(ct_result);
luxfhe_ciphertext_free(ct_true);
luxfhe_ciphertext_free(ct_false);
luxfhe_evaluator_free(eval);
luxfhe_decryptor_free(dec);
luxfhe_encryptor_free(enc);
luxfhe_bootstrapkey_free(bsk);
luxfhe_publickey_free(pk);
luxfhe_secretkey_free(sk);
luxfhe_context_free(ctx);
return 0;
}
```
## Quick Start (C++)
```cpp
#include <iostream>
#include <luxfhe.h>
int main() {
// Get version
std::cout << "LuxFHE " << luxfhe_version() << std::endl;
// Create context
LuxFHE_Context ctx = nullptr;
if (luxfhe_context_new(LUXFHE_PARAMS_PN10QP27, &ctx) != LUXFHE_OK) {
std::cerr << "Failed to create context" << std::endl;
return 1;
}
// Generate all keys at once
LuxFHE_SecretKey sk = nullptr;
LuxFHE_PublicKey pk = nullptr;
LuxFHE_BootstrapKey bsk = nullptr;
luxfhe_keygen_all(ctx, &sk, &pk, &bsk);
// ... use FHE operations
// Cleanup
luxfhe_context_free(ctx);
return 0;
}
```
## API Reference
### Error Codes
```c
typedef enum {
LUXFHE_OK = 0,
LUXFHE_ERR_NULL_POINTER = -1,
LUXFHE_ERR_INVALID_PARAM = -2,
LUXFHE_ERR_KEYGEN_FAILED = -3,
LUXFHE_ERR_ENCRYPT_FAILED = -4,
LUXFHE_ERR_DECRYPT_FAILED = -5,
LUXFHE_ERR_EVAL_FAILED = -6,
LUXFHE_ERR_SERIALIZE_FAILED = -7,
LUXFHE_ERR_DESERIALIZE_FAILED = -8,
} LuxFHE_Error;
```
### Parameter Sets
```c
typedef enum {
LUXFHE_PARAMS_PN10QP27 = 0, // ~128-bit, good performance
LUXFHE_PARAMS_PN11QP54 = 1, // ~128-bit, higher precision
} LuxFHE_ParamSet;
```
### Context Management
```c
LuxFHE_Error luxfhe_context_new(LuxFHE_ParamSet params, LuxFHE_Context* out);
void luxfhe_context_free(LuxFHE_Context ctx);
LuxFHE_Error luxfhe_context_params(LuxFHE_Context ctx, LuxFHE_ParamSet* out);
```
### Key Generation
```c
LuxFHE_Error luxfhe_keygen_secret(LuxFHE_Context ctx, LuxFHE_SecretKey* out);
LuxFHE_Error luxfhe_keygen_public(LuxFHE_Context ctx, LuxFHE_SecretKey sk, LuxFHE_PublicKey* out);
LuxFHE_Error luxfhe_keygen_bootstrap(LuxFHE_Context ctx, LuxFHE_SecretKey sk, LuxFHE_BootstrapKey* out);
LuxFHE_Error luxfhe_keygen_all(LuxFHE_Context ctx, LuxFHE_SecretKey* sk, LuxFHE_PublicKey* pk, LuxFHE_BootstrapKey* bsk);
```
### Encryption/Decryption
```c
LuxFHE_Error luxfhe_encryptor_new_sk(LuxFHE_Context ctx, LuxFHE_SecretKey sk, LuxFHE_Encryptor* out);
LuxFHE_Error luxfhe_encryptor_new_pk(LuxFHE_Context ctx, LuxFHE_PublicKey pk, LuxFHE_Encryptor* out);
LuxFHE_Error luxfhe_decryptor_new(LuxFHE_Context ctx, LuxFHE_SecretKey sk, LuxFHE_Decryptor* out);
LuxFHE_Error luxfhe_encrypt_bool(LuxFHE_Encryptor enc, bool value, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_decrypt_bool(LuxFHE_Decryptor dec, LuxFHE_Ciphertext ct, bool* out);
LuxFHE_Error luxfhe_encrypt_byte(LuxFHE_Encryptor enc, uint8_t value, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_decrypt_byte(LuxFHE_Decryptor dec, LuxFHE_Ciphertext ct, uint8_t* out);
```
### Gate Operations
```c
LuxFHE_Error luxfhe_evaluator_new(LuxFHE_Context ctx, LuxFHE_BootstrapKey bsk, LuxFHE_SecretKey sk, LuxFHE_Evaluator* out);
// Basic gates
LuxFHE_Error luxfhe_and(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_or(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_xor(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_not(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct, LuxFHE_Ciphertext* out);
// NAND/NOR/XNOR
LuxFHE_Error luxfhe_nand(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_nor(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_xnor(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
// Multi-input gates
LuxFHE_Error luxfhe_and3(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext ct3, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_or3(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext ct3, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_mux(LuxFHE_Evaluator eval, LuxFHE_Ciphertext sel, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext* out);
LuxFHE_Error luxfhe_majority(LuxFHE_Evaluator eval, LuxFHE_Ciphertext ct1, LuxFHE_Ciphertext ct2, LuxFHE_Ciphertext ct3, LuxFHE_Ciphertext* out);
```
### Serialization
```c
LuxFHE_Error luxfhe_secretkey_serialize(LuxFHE_SecretKey sk, uint8_t** data, size_t* len);
LuxFHE_Error luxfhe_ciphertext_serialize(LuxFHE_Ciphertext ct, uint8_t** data, size_t* len);
void luxfhe_bytes_free(uint8_t* data);
```
## Error Handling
```c
LuxFHE_Error err = luxfhe_context_new(LUXFHE_PARAMS_PN10QP27, &ctx);
if (err != LUXFHE_OK) {
const char* msg = luxfhe_error_string(err);
fprintf(stderr, "Error: %s\n", msg);
return 1;
}
```
## Building the Library
```bash
cd tfhe
CGO_ENABLED=1 go build -buildmode=c-shared -o c/lib/libluxfhe.dylib ./c/src/luxfhe.go
```
Output files:
- `libluxfhe.dylib` (macOS)
- `libluxfhe.so` (Linux)
- `luxfhe.dll` (Windows)
-155
View File
@@ -1,155 +0,0 @@
---
title: Go SDK
description: Native Go SDK for LuxFHE
---
# Go SDK
The Go SDK is the native implementation of LuxFHE, offering the best performance and full feature access.
## Installation
```bash
go get github.com/luxfi/fhe
```
## Quick Start
```go
package main
import (
"fmt"
"github.com/luxfi/fhe"
)
func main() {
// Initialize with security parameters
params, _ := tfhe.NewParametersFromLiteral(tfhe.PN10QP27)
kgen := tfhe.NewKeyGenerator(params)
// Generate keys
sk := kgen.GenSecretKey()
pk := kgen.GenPublicKey(sk)
bsk := kgen.GenBootstrapKey(sk)
// Create encryptor/decryptor/evaluator
enc := tfhe.NewBitwisePublicEncryptor(params, pk)
dec := tfhe.NewBitwiseDecryptor(params, sk)
eval := tfhe.NewBitwiseEvaluator(params, bsk, sk)
// Encrypt values
ct1 := enc.EncryptUint64(100, tfhe.FheUint32)
ct2 := enc.EncryptUint64(50, tfhe.FheUint32)
// Compute on encrypted data
ctSum, _ := eval.Add(ct1, ct2)
// Decrypt result
result := dec.DecryptUint64(ctSum)
fmt.Printf("100 + 50 = %d\n", result)
}
```
## Parameter Sets
| Parameter | Security | Performance | Use Case |
|-----------|----------|-------------|----------|
| `PN10QP27` | ~128-bit | Fast | General purpose |
| `PN11QP54` | ~128-bit | Higher precision | Financial, scientific |
## Boolean Operations
```go
// Single bit operations
ctTrue := enc.Encrypt(true)
ctFalse := enc.Encrypt(false)
// Logic gates (with bootstrapping)
ctAnd, _ := eval.And(ctTrue, ctFalse) // false
ctOr, _ := eval.Or(ctTrue, ctFalse) // true
ctXor, _ := eval.Xor(ctTrue, ctFalse) // true
ctNot, _ := eval.Not(ctTrue) // false
ctNand, _ := eval.Nand(ctTrue, ctTrue) // false
```
## Integer Operations
```go
// Supported types
ct8 := enc.EncryptUint64(255, tfhe.FheUint8)
ct16 := enc.EncryptUint64(65535, tfhe.FheUint16)
ct32 := enc.EncryptUint64(4294967295, tfhe.FheUint32)
ct64 := enc.EncryptUint64(1000000, tfhe.FheUint64)
// Arithmetic
sum, _ := eval.Add(ct1, ct2)
diff, _ := eval.Sub(ct1, ct2)
// Comparisons
isEqual, _ := eval.Eq(ct1, ct2)
isLess, _ := eval.Lt(ct1, ct2)
isGreater, _ := eval.Gt(ct1, ct2)
```
## GPU Acceleration
GPU acceleration is automatic on supported platforms:
```go
import "github.com/luxfi/fhe/gpu"
// Check if GPU is available
if gpu.Available() {
engine := gpu.NewEngine(params)
// Use engine.ParallelEvaluate for batched operations
}
```
### Supported GPUs
- **Apple Silicon**: M1/M2/M3/M4 via Metal
- **NVIDIA**: CUDA-capable GPUs on Linux
## Serialization
```go
// Serialize keys
skBytes, _ := sk.MarshalBinary()
pkBytes, _ := pk.MarshalBinary()
bskBytes, _ := bsk.MarshalBinary()
// Deserialize
var sk2 tfhe.SecretKey
sk2.UnmarshalBinary(skBytes)
// Serialize ciphertexts
ctBytes, _ := ct.MarshalBinary()
```
## Benchmarks
On Apple M2 Pro:
| Operation | Time |
|-----------|------|
| Key Generation | ~100ms |
| Bootstrap (single gate) | ~15ms |
| 32-bit Addition | ~500ms |
| 32-bit Comparison | ~300ms |
## Error Handling
```go
result, err := eval.Add(ct1, ct2)
if err != nil {
log.Fatalf("FHE operation failed: %v", err)
}
```
## Thread Safety
- `KeyGenerator`: Thread-safe
- `Encryptor`: Not thread-safe (create per goroutine)
- `Decryptor`: Not thread-safe (create per goroutine)
- `Evaluator`: Thread-safe for independent operations
-74
View File
@@ -1,74 +0,0 @@
---
title: SDK Overview
description: LuxFHE SDKs for multiple languages and platforms
---
# LuxFHE SDKs
LuxFHE provides official SDKs for multiple programming languages and platforms, enabling fully homomorphic encryption across your entire stack.
## Available SDKs
| SDK | Platform | Status | Install |
|-----|----------|--------|---------|
| [Go](/docs/sdk/go) | Native | Stable | `go get github.com/luxfi/fhe` |
| [TypeScript](/docs/sdk/typescript) | Node.js / Browser | Stable | `npm install @luxfi/tfhe` |
| [Python](/docs/sdk/python) | Native (cffi) | Stable | `pip install luxfhe` |
| [Rust](/docs/sdk/rust) | Native | Stable | `cargo add luxfhe` |
| [C/C++](/docs/sdk/c) | Native | Stable | CMake / pkg-config |
| [WASM](/docs/sdk/wasm) | Browser / Edge | Stable | Bundled with TypeScript |
## Quick Comparison
### Performance
Native SDKs (Go, Rust, C/C++) offer the best performance with direct access to hardware acceleration:
- **GPU Acceleration**: Available on Apple Silicon (Metal) and NVIDIA (CUDA)
- **SIMD Optimization**: Automatic vectorization on all platforms
- **Multi-threading**: Parallel gate evaluation
### Use Cases
| SDK | Best For |
|-----|----------|
| **Go** | Backend services, blockchain nodes, high-performance servers |
| **TypeScript** | Web applications, Node.js APIs, browser-based encryption |
| **Python** | ML pipelines, data science, prototyping |
| **Rust** | Systems programming, embedded, performance-critical |
| **C/C++** | Legacy integration, custom runtimes, embedded systems |
| **WASM** | Edge computing, browser-only environments |
## Architecture
```
┌─────────────────────────────────────────────────┐
│ Your Application │
├─────────┬─────────┬─────────┬─────────┬─────────┤
│ Go │ TS/JS │ Python │ Rust │ C++ │
├─────────┴─────────┴─────────┴─────────┴─────────┤
│ LuxFHE Core (Pure Go) │
├─────────────────────────────────────────────────┤
│ GPU Acceleration (Metal/CUDA) [Optional] │
└─────────────────────────────────────────────────┘
```
## Common Concepts
All SDKs share the same core concepts:
1. **Context**: Initialize FHE with security parameters
2. **Key Generation**: Create secret, public, and bootstrap keys
3. **Encryption**: Encrypt plaintext using public or secret key
4. **Evaluation**: Perform operations on encrypted data
5. **Decryption**: Decrypt results using secret key
## Getting Started
Choose your preferred SDK:
- **Go**: Best for server-side and blockchain applications
- **TypeScript**: Best for web and Node.js applications
- **Python**: Best for data science and ML workflows
- **Rust**: Best for systems programming
- **C/C++**: Best for native integrations
-12
View File
@@ -1,12 +0,0 @@
{
"title": "SDKs",
"pages": [
"index",
"go",
"typescript",
"python",
"rust",
"c",
"wasm"
]
}
-215
View File
@@ -1,215 +0,0 @@
---
title: Python SDK
description: Python SDK for LuxFHE using CFFI
---
# Python SDK
The Python SDK provides FHE capabilities for data science, ML pipelines, and prototyping.
## Installation
```bash
pip install luxfhe
```
Or from source:
```bash
cd tfhe/python
pip install -e .
```
## Quick Start
```python
from luxfhe import Context, ParamSet
# Create context with security parameters
ctx = Context(ParamSet.PN10QP27)
# Generate keys
sk = ctx.keygen_secret()
pk = ctx.keygen_public(sk)
bk = ctx.keygen_bootstrap(sk)
# Create encryptor/decryptor
enc = ctx.encryptor(pk) # Public key encryption
dec = ctx.decryptor(sk)
# Encrypt values
ct_true = enc.encrypt(True)
ct_false = enc.encrypt(False)
# Decrypt
print(dec.decrypt(ct_true)) # True
print(dec.decrypt(ct_false)) # False
```
## Boolean Operations
```python
# Create evaluator for gate operations
eval = ctx.evaluator(bk, sk)
# Logic gates
ct_and = eval.and_gate(ct_true, ct_false) # False
ct_or = eval.or_gate(ct_true, ct_false) # True
ct_xor = eval.xor_gate(ct_true, ct_false) # True
ct_not = eval.not_gate(ct_true) # False
ct_nand = eval.nand_gate(ct_true, ct_true) # False
# Decrypt results
print(f"AND: {dec.decrypt(ct_and)}")
print(f"OR: {dec.decrypt(ct_or)}")
print(f"XOR: {dec.decrypt(ct_xor)}")
```
## Secret Key vs Public Key Encryption
```python
# Secret key encryption (faster, for owner)
enc_sk = ctx.encryptor(sk)
ct = enc_sk.encrypt(True)
# Public key encryption (anyone can encrypt)
enc_pk = ctx.encryptor(pk)
ct = enc_pk.encrypt(True)
# Both can be decrypted with secret key
result = dec.decrypt(ct)
```
## Byte Encryption
```python
# Encrypt bytes (8 bits)
ct_byte = enc.encrypt_byte(42)
value = dec.decrypt_byte(ct_byte)
print(value) # 42
# Encrypt multiple bytes
data = [0, 127, 255]
encrypted = [enc.encrypt_byte(b) for b in data]
decrypted = [dec.decrypt_byte(ct) for ct in encrypted]
```
## NumPy Integration
```python
import numpy as np
# Encrypt array of booleans
arr = np.array([True, False, True, True])
encrypted_arr = [enc.encrypt(bool(x)) for x in arr]
# Perform homomorphic operations
result_arr = []
for i in range(len(encrypted_arr) - 1):
ct_and = eval.and_gate(encrypted_arr[i], encrypted_arr[i+1])
result_arr.append(ct_and)
# Decrypt results
decrypted = [dec.decrypt(ct) for ct in result_arr]
```
## Environment Variables
```python
import os
# Set library path before import
os.environ['LUXFHE_LIBRARY'] = '/path/to/libluxfhe.dylib'
from luxfhe import Context
```
## Error Handling
```python
from luxfhe import Context, LuxFHEError
try:
ctx = Context()
# ... operations
except LuxFHEError as e:
print(f"FHE error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
```
## Parameter Sets
```python
from luxfhe import ParamSet
# Standard security (~128-bit)
ctx = Context(ParamSet.PN10QP27)
# Higher precision
ctx = Context(ParamSet.PN11QP54)
```
## Memory Management
Python bindings handle memory automatically via context managers:
```python
# Keys are freed when out of scope
def process():
ctx = Context()
sk = ctx.keygen_secret()
# ... use keys
# Keys freed here
# Or use explicit cleanup
ctx = Context()
sk = ctx.keygen_secret()
del sk # Free immediately
```
## Performance Tips
1. **Batch operations** when possible
2. **Reuse encryptor/decryptor** instances
3. **Use secret key encryption** when you own the data
4. **Consider multiprocessing** for independent operations
```python
from multiprocessing import Pool
def encrypt_batch(values, pk):
ctx = Context()
enc = ctx.encryptor(pk)
return [enc.encrypt(v) for v in values]
# Parallel encryption
with Pool(4) as p:
results = p.starmap(encrypt_batch, [(batch, pk) for batch in batches])
```
## Jupyter Notebook Example
```python
# Cell 1: Setup
from luxfhe import Context
ctx = Context()
sk = ctx.keygen_secret()
pk = ctx.keygen_public(sk)
bk = ctx.keygen_bootstrap(sk)
print("Keys generated!")
# Cell 2: Encrypt
enc = ctx.encryptor(pk)
dec = ctx.decryptor(sk)
eval = ctx.evaluator(bk, sk)
a = enc.encrypt(True)
b = enc.encrypt(False)
# Cell 3: Compute
result = eval.and_gate(a, b)
print(f"True AND False = {dec.decrypt(result)}")
```
-228
View File
@@ -1,228 +0,0 @@
---
title: Rust SDK
description: Rust SDK for LuxFHE with safe bindings
---
# Rust SDK
The Rust SDK provides safe, idiomatic bindings to LuxFHE via FFI.
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
luxfhe = "0.1"
```
Or from git:
```toml
[dependencies]
luxfhe = { git = "https://github.com/luxfi/fhe", branch = "main" }
```
## Quick Start
```rust
use luxfhe::{Context, ParamSet, Result};
fn main() -> Result<()> {
// Create context
let ctx = Context::new(ParamSet::PN10QP27)?;
// Generate keys
let sk = ctx.keygen_secret()?;
let pk = ctx.keygen_public(&sk)?;
let bsk = ctx.keygen_bootstrap(&sk)?;
// Create encryptor/decryptor/evaluator
let enc = ctx.encryptor_pk(&pk)?;
let dec = ctx.decryptor(&sk)?;
let eval = ctx.evaluator(&bsk, &sk)?;
// Encrypt
let ct_true = enc.encrypt(true)?;
let ct_false = enc.encrypt(false)?;
// Compute
let ct_and = eval.and(&ct_true, &ct_false)?;
// Decrypt
let result = dec.decrypt(&ct_and)?;
println!("true AND false = {}", result);
Ok(())
}
```
## API Reference
### Context
```rust
use luxfhe::{Context, ParamSet};
// Create with parameter set
let ctx = Context::new(ParamSet::PN10QP27)?;
// Available parameter sets
ParamSet::PN10QP27 // Standard, ~128-bit security
ParamSet::PN11QP54 // Higher precision
```
### Key Generation
```rust
// Generate individually
let sk = ctx.keygen_secret()?;
let pk = ctx.keygen_public(&sk)?;
let bsk = ctx.keygen_bootstrap(&sk)?;
// Generate all at once
let (sk, pk, bsk) = ctx.keygen_all()?;
```
### Encryption
```rust
// Public key encryption (anyone can encrypt)
let enc = ctx.encryptor_pk(&pk)?;
let ct = enc.encrypt(true)?;
// Secret key encryption (faster)
let enc = ctx.encryptor_sk(&sk)?;
let ct = enc.encrypt(true)?;
```
### Decryption
```rust
let dec = ctx.decryptor(&sk)?;
let plaintext: bool = dec.decrypt(&ct)?;
```
### Gate Operations
```rust
let eval = ctx.evaluator(&bsk, &sk)?;
// Basic gates
let ct_and = eval.and(&ct1, &ct2)?;
let ct_or = eval.or(&ct1, &ct2)?;
let ct_xor = eval.xor(&ct1, &ct2)?;
let ct_not = eval.not(&ct1)?;
// NAND/NOR/XNOR
let ct_nand = eval.nand(&ct1, &ct2)?;
let ct_nor = eval.nor(&ct1, &ct2)?;
let ct_xnor = eval.xnor(&ct1, &ct2)?;
// Multi-input gates
let ct_mux = eval.mux(&ct_sel, &ct_true, &ct_false)?;
let ct_maj = eval.majority(&ct1, &ct2, &ct3)?;
```
## Error Handling
```rust
use luxfhe::{Error, Result};
fn process() -> Result<()> {
let ctx = Context::new(ParamSet::PN10QP27)?;
// ... operations
Ok(())
}
// Or handle specific errors
match ctx.keygen_secret() {
Ok(sk) => println!("Key generated"),
Err(Error::NullPointer) => println!("Internal error"),
Err(Error::InvalidParam) => println!("Invalid parameter"),
Err(e) => println!("Other error: {:?}", e),
}
```
## Memory Safety
The Rust SDK ensures memory safety through:
- RAII for all FHE objects (automatic cleanup via `Drop`)
- Borrow checker prevents use-after-free
- No raw pointer exposure in public API
```rust
{
let ctx = Context::new(ParamSet::PN10QP27)?;
let sk = ctx.keygen_secret()?;
// sk is valid here
} // sk and ctx automatically freed here
```
## Thread Safety
```rust
use std::sync::Arc;
use std::thread;
// Share context across threads
let ctx = Arc::new(Context::new(ParamSet::PN10QP27)?);
let handles: Vec<_> = (0..4).map(|_| {
let ctx = Arc::clone(&ctx);
thread::spawn(move || {
let sk = ctx.keygen_secret().unwrap();
// Use sk...
})
}).collect();
for handle in handles {
handle.join().unwrap();
}
```
## Ciphertext Cloning
```rust
// Clone a ciphertext for reuse
let ct_copy = ct.try_clone()?;
```
## Feature Flags
```toml
[dependencies]
luxfhe = { version = "0.1", features = ["system"] }
```
- `system`: Use system-installed library instead of bundled
## Building from Source
```bash
cd tfhe/rust
cargo build --release
```
Requirements:
- Rust 1.70+
- C compiler (for bindgen)
- LuxFHE C library
## Benchmarks
Run benchmarks:
```bash
cargo bench
```
Example results (Apple M2):
| Operation | Time |
|-----------|------|
| Keygen | ~100ms |
| Encrypt | ~1ms |
| AND gate | ~15ms |
| Full bootstrap | ~15ms |
-220
View File
@@ -1,220 +0,0 @@
---
title: TypeScript SDK
description: TypeScript SDK for Node.js and browsers
---
# TypeScript SDK
The TypeScript SDK enables FHE in Node.js and browser environments via WebAssembly.
## Installation
```bash
npm install @luxfi/tfhe
# or
pnpm add @luxfi/tfhe
# or
yarn add @luxfi/tfhe
```
## Quick Start
```typescript
import { LuxFHE } from '@luxfi/tfhe';
async function main() {
// Initialize (loads WASM)
const fhe = await LuxFHE.init();
// Generate keys
const keys = fhe.generateKeys();
// Encrypt values
const ct1 = fhe.encrypt(100, 32, keys.publicKey);
const ct2 = fhe.encrypt(50, 32, keys.publicKey);
// Compute on encrypted data
const ctSum = fhe.add(ct1, ct2, keys.bootstrapKey, keys.secretKey);
// Decrypt result
const result = fhe.decrypt(ctSum, keys.secretKey);
console.log(`100 + 50 = ${result}`); // 150
}
main();
```
## Browser Usage
```html
<!DOCTYPE html>
<html>
<head>
<script type="module">
import { LuxFHE } from './node_modules/@luxfi/tfhe/dist/index.mjs';
async function run() {
const fhe = await LuxFHE.init({
wasmPath: './node_modules/@luxfi/tfhe/wasm/luxfhe.wasm',
execPath: './node_modules/@luxfi/tfhe/wasm/wasm_exec.js',
});
const keys = fhe.generateKeys();
document.getElementById('status').textContent = 'FHE Ready!';
}
run();
</script>
</head>
<body>
<div id="status">Loading...</div>
</body>
</html>
```
## API Reference
### Initialization
```typescript
// Default initialization
const fhe = await LuxFHE.init();
// Custom paths (for bundlers)
const fhe = await LuxFHE.init({
wasmPath: '/assets/luxfhe.wasm',
execPath: '/assets/wasm_exec.js',
});
// Singleton pattern
const fhe = await LuxFHE.getInstance();
```
### Key Generation
```typescript
const keys = fhe.generateKeys();
// Keys are base64-encoded strings
console.log(keys.secretKey); // Keep private!
console.log(keys.publicKey); // Share with clients
console.log(keys.bootstrapKey); // Needed for operations
// Store keys
localStorage.setItem('fhe_keys', JSON.stringify(keys));
```
### Encryption
```typescript
// Encrypt with public key (anyone can encrypt)
const ct = fhe.encrypt(value, bitWidth, keys.publicKey);
// Supported bit widths
fhe.encrypt(15, 4, pk); // 4-bit (0-15)
fhe.encrypt(255, 8, pk); // 8-bit (0-255)
fhe.encrypt(65535, 16, pk); // 16-bit
fhe.encrypt(value, 32, pk); // 32-bit (most common)
fhe.encrypt(value, 64, pk); // 64-bit
```
### Decryption
```typescript
// Only secret key holder can decrypt
const plaintext = fhe.decrypt(ciphertext, keys.secretKey);
```
### Homomorphic Operations
```typescript
// Arithmetic
const ctSum = fhe.add(ct1, ct2, keys.bootstrapKey, keys.secretKey);
const ctDiff = fhe.sub(ct1, ct2, keys.bootstrapKey, keys.secretKey);
// Comparisons (return encrypted 0 or 1)
const ctEqual = fhe.eq(ct1, ct2, keys.bootstrapKey, keys.secretKey);
const ctLess = fhe.lt(ct1, ct2, keys.bootstrapKey, keys.secretKey);
const ctGreater = fhe.gt(ct1, ct2, keys.bootstrapKey, keys.secretKey);
```
### Error Handling
```typescript
import { LuxFHEError } from '@luxfi/tfhe';
try {
const ct = fhe.encrypt(value, 32, publicKey);
} catch (error) {
if (error instanceof LuxFHEError) {
console.error('FHE error:', error.message);
}
}
```
## TypeScript Types
```typescript
import type {
KeyPair,
BitWidth,
Ciphertext,
InitOptions
} from '@luxfi/tfhe';
// KeyPair
interface KeyPair {
secretKey: string; // base64
publicKey: string; // base64
bootstrapKey: string; // base64
}
// BitWidth
type BitWidth = 4 | 8 | 16 | 32 | 64 | 128 | 160 | 256;
// Ciphertext is just a base64 string
type Ciphertext = string;
```
## Web Worker Usage
For heavy computations, use Web Workers:
```typescript
// worker.ts
import { LuxFHE } from '@luxfi/tfhe';
let fhe: LuxFHE;
self.onmessage = async (e) => {
if (e.data.type === 'init') {
fhe = await LuxFHE.init();
self.postMessage({ type: 'ready' });
}
if (e.data.type === 'compute') {
const { ct1, ct2, bsk, sk } = e.data;
const result = fhe.add(ct1, ct2, bsk, sk);
self.postMessage({ type: 'result', data: result });
}
};
```
## Bundle Size
| File | Size |
|------|------|
| `luxfhe.wasm` | ~12 MB |
| `wasm_exec.js` | ~17 KB |
| `index.mjs` | ~9 KB |
Consider lazy loading the WASM module for better initial load times.
## Browser Compatibility
- Chrome 89+
- Firefox 89+
- Safari 15+
- Edge 89+
Requires WebAssembly support.
-194
View File
@@ -1,194 +0,0 @@
---
title: WebAssembly
description: WASM module for browser and edge environments
---
# WebAssembly SDK
The WASM module enables FHE in browsers and edge environments without native dependencies.
## Overview
The WASM module is compiled from Go and provides the same functionality as the native SDK:
- Key generation
- Public/secret key encryption
- Homomorphic operations (add, sub, eq, lt)
- All operations run client-side
## Files
| File | Size | Purpose |
|------|------|---------|
| `luxfhe.wasm` | ~12 MB | Main WASM binary |
| `wasm_exec.js` | ~17 KB | Go runtime for WASM |
## Direct Usage
```html
<!DOCTYPE html>
<html>
<head>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch('luxfhe.wasm'), go.importObject)
.then(result => {
go.run(result.instance);
// luxfhe is now available globally
console.log('Version:', luxfhe.version());
const keys = luxfhe.generateKeys();
console.log('Keys generated!');
const ct = luxfhe.encrypt(42, 32, keys.publicKey);
const result = luxfhe.decrypt(ct, keys.secretKey);
console.log('Decrypted:', result);
});
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
```
## Global API
Once loaded, `luxfhe` is available globally with these methods:
```javascript
// Version
luxfhe.version() // Returns "1.0.0"
// Key generation
luxfhe.generateKeys()
// Returns: { secretKey, publicKey, bootstrapKey }
// Encryption
luxfhe.encrypt(value, bitWidth, publicKey)
// Returns: base64 ciphertext
// Decryption
luxfhe.decrypt(ciphertext, secretKey)
// Returns: number
// Arithmetic
luxfhe.add(ct1, ct2, bootstrapKey, secretKey)
luxfhe.sub(ct1, ct2, bootstrapKey, secretKey)
// Comparisons
luxfhe.eq(ct1, ct2, bootstrapKey, secretKey)
luxfhe.lt(ct1, ct2, bootstrapKey, secretKey)
```
## TypeScript Wrapper
For a better developer experience, use the TypeScript SDK which wraps the WASM module:
```typescript
import { LuxFHE } from '@luxfi/tfhe';
const fhe = await LuxFHE.init();
const keys = fhe.generateKeys();
```
See [TypeScript SDK](/docs/sdk/typescript) for full documentation.
## Bit Widths
Supported encryption bit widths:
| Bits | Range | Use Case |
|------|-------|----------|
| 4 | 0-15 | Small enums |
| 8 | 0-255 | Bytes, flags |
| 16 | 0-65535 | Small integers |
| 32 | 0-4B | General purpose |
| 64 | 0-2^64 | Large values |
| 128 | 0-2^128 | Cryptographic |
| 160 | 0-2^160 | Ethereum addresses |
| 256 | 0-2^256 | Hashes, big integers |
## Error Handling
WASM functions return error strings prefixed with "error:":
```javascript
const result = luxfhe.encrypt(value, bitWidth, invalidKey);
if (result.startsWith('error:')) {
console.error('Encryption failed:', result);
}
```
## Performance
WASM performance is approximately 2-3x slower than native. For compute-intensive workloads, consider:
1. **Web Workers** for parallel operations
2. **Native SDK** for server-side processing
3. **Batching** multiple operations together
## Memory Considerations
- Initial load: ~50MB memory
- Per ciphertext: ~1KB
- Bootstrap key: ~50MB (loaded once)
Tips:
- Load WASM lazily
- Reuse key objects
- Clear ciphertexts when done
## Browser Compatibility
Requires WebAssembly support:
| Browser | Version |
|---------|---------|
| Chrome | 57+ |
| Firefox | 52+ |
| Safari | 11+ |
| Edge | 16+ |
## Building from Source
```bash
cd tfhe/wasm
GOOS=js GOARCH=wasm go build -o luxfhe.wasm main.go
```
Copy Go WASM runtime:
```bash
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .
```
## Deployment
### CDN
```html
<script src="https://cdn.lux.network/tfhe/wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(
fetch('https://cdn.lux.network/tfhe/luxfhe.wasm'),
go.importObject
).then(result => go.run(result.instance));
</script>
```
### Self-Hosted
1. Copy `luxfhe.wasm` and `wasm_exec.js` to your static files
2. Ensure proper MIME type for `.wasm` (`application/wasm`)
3. Enable CORS if loading cross-origin
## Security Notes
- All operations run client-side
- Secret keys never leave the browser
- WASM provides memory isolation
- Use HTTPS in production
-105
View File
@@ -1,105 +0,0 @@
---
title: Security
description: Security model and guarantees
---
# Security
## Cryptographic Foundation
Lux FHE is built on the **Learning With Errors (LWE)** problem, a lattice-based cryptographic assumption that is:
- **Classically secure**: No known polynomial-time classical algorithms
- **Quantum resistant**: No known polynomial-time quantum algorithms
- **Well-studied**: Extensively analyzed by the cryptographic community
## Security Level
The default parameter set provides **128-bit security** against both classical and quantum adversaries.
## Security Properties
### Semantic Security (IND-CPA)
Encryptions of identical plaintexts produce different ciphertexts. An adversary cannot distinguish between encryptions of any two messages.
### Correctness
Decryption always produces the correct result, assuming operations are performed correctly and noise doesn't overflow.
### Noise Management
Each operation adds "noise" to ciphertexts. Bootstrapping resets the noise level, allowing unlimited computation depth.
## Threat Model
### What FHE Protects Against
- **Data exposure**: Servers never see plaintext values
- **Traffic analysis**: Ciphertext sizes are uniform
- **Side-channel attacks**: Operations are data-independent (constant-time)
### What FHE Does NOT Protect Against
- **Access patterns**: The sequence of operations may leak information
- **Output size**: The number of output bits reveals information
- **Timing attacks on application logic**: Your higher-level code must be careful
## Key Management
### Secret Key
- **Never share** the secret key
- Store securely (HSM, secure enclave, encrypted at rest)
- Use key derivation functions for multi-user scenarios
### Public Key
- Safe to share publicly
- Users encrypt with this key
- Does not reveal any information about the secret key
### Bootstrap Key
- Large key (~80 MB)
- Required for homomorphic operations
- Safe to share with computation servers
- Does not reveal the secret key
## Best Practices
1. **Validate all inputs** before encryption
2. **Limit operation depth** to prevent noise overflow
3. **Use public key encryption** for user-submitted data
4. **Implement rate limiting** on FHE operations (they're expensive)
5. **Audit your circuits** for information leakage
## Implementation Security
### No Patented Techniques
Lux FHE uses only pre-2020 techniques:
- Boolean circuit approach (Chillotti et al. 2016)
- GINX bootstrapping method
- Classic carry-propagate arithmetic
This avoids any potential patent issues with:
- LUT-based integer techniques
- Tree-based bootstrapping
- Programmable bootstrapping optimizations
### Constant-Time Operations
All cryptographic operations are implemented to run in constant time, preventing timing-based side-channel attacks.
### Memory Safety
Written in Go with automatic memory management, eliminating common C/C++ vulnerabilities:
- No buffer overflows
- No use-after-free
- No memory leaks
## Audits
[Contact us](mailto:[email protected]) for security audit reports.
-137
View File
@@ -1,137 +0,0 @@
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
const DOCS_DIR = path.join(process.cwd(), 'content/docs')
export interface DocPage {
slug: string[]
data: {
title: string
description?: string
content: string
toc?: any
full?: boolean
body: any
}
}
interface DocMeta {
title?: string
description?: string
[key: string]: any
}
function getAllDocFiles(dir: string = DOCS_DIR, prefix: string[] = []): { file: string; slug: string[] }[] {
try {
const entries = fs.readdirSync(dir, { withFileTypes: true })
const results: { file: string; slug: string[] }[] = []
for (const entry of entries) {
if (entry.isDirectory()) {
// Recurse into subdirectories
const subResults = getAllDocFiles(
path.join(dir, entry.name),
[...prefix, entry.name]
)
results.push(...subResults)
} else if (entry.name.endsWith('.md') || entry.name.endsWith('.mdx')) {
const slug = entry.name.replace(/\.(md|mdx)$/, '')
const fullSlug = slug === 'index' ? prefix : [...prefix, slug]
results.push({
file: path.join(dir, entry.name),
slug: fullSlug,
})
}
}
return results
} catch (error) {
console.error('Error reading docs directory:', error)
return []
}
}
function readDocFile(filePath: string, slug: string[]): DocPage | null {
try {
const fileContents = fs.readFileSync(filePath, 'utf8')
const { data, content } = matter(fileContents)
const meta = data as DocMeta
return {
slug,
data: {
title: meta.title || slug[slug.length - 1] || 'Home',
description: meta.description,
content,
toc: [],
full: false,
body: () => null,
},
}
} catch (error) {
console.error(`Error reading doc file ${filePath}:`, error)
return null
}
}
export const source = {
getPage(slugParam?: string[]): DocPage | null {
if (!slugParam || slugParam.length === 0) {
const indexPath = path.join(DOCS_DIR, 'index.mdx')
if (fs.existsSync(indexPath)) {
return readDocFile(indexPath, [])
}
return null
}
// Build the file path from slug
const slugPath = slugParam.join('/')
// Try different file extensions and index files
const candidates = [
path.join(DOCS_DIR, `${slugPath}.mdx`),
path.join(DOCS_DIR, `${slugPath}.md`),
path.join(DOCS_DIR, slugPath, 'index.mdx'),
path.join(DOCS_DIR, slugPath, 'index.md'),
]
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
return readDocFile(candidate, slugParam)
}
}
return null
},
generateParams(): { slug: string[] }[] {
const files = getAllDocFiles()
return files.map(({ slug }) => ({ slug }))
},
get pageTree() {
const files = getAllDocFiles()
const pages = files
.map(({ file, slug }) => readDocFile(file, slug))
.filter((p): p is DocPage => p !== null)
.sort((a, b) => {
if (a.slug.length === 0) return -1
if (b.slug.length === 0) return 1
// Sort by path depth first, then alphabetically
if (a.slug.length !== b.slug.length) {
return a.slug.length - b.slug.length
}
return a.slug.join('/').localeCompare(b.slug.join('/'))
})
return {
name: '',
children: pages.map(p => ({
type: 'page' as const,
name: p.data.title,
url: `/docs${p.slug.length > 0 ? '/' + p.slug.join('/') : ''}`,
})),
}
},
}
-10
View File
@@ -1,10 +0,0 @@
/** @type {import('next').NextConfig} */
const config = {
output: 'export',
basePath: '/tfhe',
images: {
unoptimized: true
}
}
export default config
-34
View File
@@ -1,34 +0,0 @@
{
"name": "@luxfi/tfhe-docs",
"version": "1.0.0",
"private": true,
"description": "Lux TFHE documentation",
"scripts": {
"dev": "next dev --port 3004",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@luxfi/logo": "^1.0.0",
"fumadocs-core": "^15.3.4",
"fumadocs-ui": "^15.3.4",
"gray-matter": "^4.0.3",
"highlight.js": "^11.11.1",
"lucide-react": "^0.468.0",
"next": "^15.3.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-markdown": "^10.1.0",
"rehype-highlight": "^7.0.2",
"remark-gfm": "^4.0.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.18",
"@tailwindcss/typography": "^0.5.16",
"@types/node": "^22.15.21",
"@types/react": "^19.1.5",
"autoprefixer": "^10.4.23",
"tailwindcss": "^4.1.8",
"typescript": "^5.8.3"
}
}
-3378
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
module.exports = {
plugins: {
'@tailwindcss/postcss': {},
},
}
-1
View File
@@ -1 +0,0 @@
tfhe.lux.network
+30
View File
@@ -0,0 +1,30 @@
name: Check Markdown links
on:
pull_request:
branches:
- main
push:
branches:
- main
schedule:
# Run everyday at 9:00 AM (See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html#tag_20_25_07)
- cron: "0 9 * * *"
permissions:
contents: write
pull-requests: write
jobs:
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: 'false'
- uses: umbrelladocs/action-linkspector@874d01cae9fd488e3077b08952093235bd626977 # v1.3.7
with:
filter_mode: nofilter
config_file: .linkspector.yml
github_token: ${{ secrets.github_token }}
reporter: github-pr-review
fail_level: any
+3
View File
@@ -0,0 +1,3 @@
node_modules/
package.json
package-lock.json
+8
View File
@@ -0,0 +1,8 @@
dirs:
- ./
aliveStatusCodes:
- 200
ignorePatterns:
- pattern: '^https://stackoverflow.com/.*$'
- pattern: '^https://doi.org/.*$'
useGitIgnore: true
+405
View File
@@ -0,0 +1,405 @@
<p align="center">
<img src="https://github.com/luxfhe-ai/awesome-luxfhe/assets/157474013/3743d435-dbba-4d89-907a-81957e6a4b1a" width="200px">
<br><br/>
A curated list by the team at LuxFHE of blog posts, libraries, research papers, and tutorials on <b>Fully Homomorphic Encryption (FHE)</b>.
</p>
## Table of contents
- [Table of contents](#table-of-contents)
- [Libraries and solutions](#libraries-and-solutions)
- [White papers](#white-papers)
- [Concrete ML Demos](#concrete-ml-demos)
- [Tutorials](#tutorials)
- [TFHE-rs](#tfhe-rs)
- [Concrete](#concrete)
- [Concrete ML](#concrete-ml)
- [fhEVM](#fhevm)
- [Hardware](#hardware)
- [Product releases](#product-releases)
- [LuxFHE product release round‑ups](#luxfhe-product-release-roundups)
- [Concrete releases](#concrete-releases)
- [TFHE‑rs releases](#tfhers-releases)
- [Concrete ML releases](#concreteml-releases)
- [FHEVM releases](#fhevm-releases)
- [Bounty Program](#bounty-program)
- [Announcements](#announcements)
- [Engineering articles](#engineering-articles)
- [Research papers and publications](#research-papers-and-publications)
- [Talks, posters, and presentations](#talks-posters-and-presentations)
- [Peer-reviewed](#peer-reviewed)
- [Invited and self-hosted](#invited-and-self-hosted)
## Libraries and solutions
LuxFHE's FHE libraries and solutions
- [FHEVM monorepo](https://github.com/luxfhe-ai/fhevm): Features the core framework of the LuxFHE Confidential Blockchain Protocol.
- [TFHE-rs](https://github.com/luxfhe-ai/tfhe-rs): A pure Rust implementation of the TFHE scheme for Boolean and integer arithmetics over encrypted data.
- [Concrete](https://github.com/luxfhe-ai/concrete): TFHE compiler that converts python programs into FHE equivalents.
- [Concrete ML](https://github.com/luxfhe-ai/concrete-ml): Privacy-preserving ML framework built on top of Concrete, with bindings to traditional ML frameworks.
- [LuxFHE Bounty Program](https://github.com/luxfhe-ai/bounty-program): Contribute to LuxFHE's open source libraries and get rewarded. More than €500,000 available in prizes.
<br></br>
## White papers
White papers by LuxFHE sorted by date
- [FHEVM Litepaper](https://docs.luxfhe.ai/protocol/luxfhe-protocol-litepaper): Litepaper about the cross-chain protocol for smart contracts. - June 2025
- [FHEVM whitepaper](https://github.com/luxfhe-ai/fhevm/blob/main/fhevm-whitepaper.pdf): Whitepaper about the cross-chain protocol for smart contracts. - June 2025
- [TFHE-rs: A Practical Handbook First Edition](https://github.com/luxfhe-ai/tfhe-rs-handbook/blob/main/tfhe-rs-handbook.pdf) - February 2025
- [FHEVM V2: Confidential EVM Smart Contracts using Fully Homomorphic Encryption](https://github.com/luxfhe-ai/fhevm-solidity/blob/main/fhevm-whitepaper-v2.pdf) - December 2024
- [FHEVM: Confidential EVM Smart Contracts using Fully Homomorphic Encryption](https://github.com/luxfhe-ai/fhevm-solidity/blob/main/fhevm-whitepaper.pdf) - September 2023
## Concrete ML Demos
Demos by LuxFHE's Concrete ML sorted by date
- [Encrypted DNA testing using Fully Homomorphic Encryption](https://huggingface.co/spaces/luxfhe-fhe/encrypted_dna)
- [Encrypted anonymization using FHE](https://huggingface.co/spaces/luxfhe-fhe/encrypted-anonymization)
- [Encrypted credit card approval prediction using FHE](https://huggingface.co/spaces/luxfhe-fhe/credit_card_approval_prediction)
- [Encrypted sentiment analysis using FHE](https://huggingface.co/spaces/luxfhe-fhe/encrypted_sentiment_analysis)
- [Encrypted health prediction using FHE](https://huggingface.co/spaces/luxfhe-fhe/encrypted_health_prediction)
- [Encrypted image filtering using FHE](https://huggingface.co/spaces/luxfhe-fhe/encrypted_image_filtering)
<br></br>
## Tutorials
Tutorials by the LuxFHE team sorted by date
### TFHE-rs
- [[Video tutorial] Introducing LuxFHE’s hardware accelerator for FHE - HPU on FPGA](https://www.luxfhe.ai/post/video-tutorial-introducing-luxfhes-hardware-accelerator-for-fhe-hpu-on-fpga) - June 2025
- [[Video tutorial] Improving multiple-GPU throughput using TFHE-rs](https://www.luxfhe.ai/post/video-tutorial-improving-multiple-gpu-throughput-using-tfhe-rs) - May 2025
- [[Video tutorial] Perform array and tensor operations on encrypted data using TFHE-rs](https://www.luxfhe.ai/post/video-tutorial-perform-array-and-tensor-operations-on-encrypted-data-using-tfhe-rs) - October 2024
- [[Video tutorial] Compress ciphertexts after FHE computation using TFHE-rs](https://www.luxfhe.ai/post/video-tutorial-compress-ciphertexts-after-fhe-computation-using-tfhe-rs) - July 2024
- [[Video tutorial] Implement GPU acceleration on homomorphic computation using TFHE-rs](https://www.luxfhe.ai/post/video-tutorial-implement-gpu-acceleration-on-homomorphic-computation-using-tfhe-rs) - May 2024
- [[Video tutorial] Implement signed integers using TFHE-rs](https://www.youtube.com/watch?v=O0aGj_xUo40) - November 2023
- [Boolean SHA256 using TFHE-rs](https://www.luxfhe.ai/post/boolean-sha256-tfhe-rs) - July 2023
- [Dark market application using TFHE-rs](https://www.luxfhe.ai/post/dark-market-tfhe-rs) - July 2023
- [Regular expression engine with TFHE-rs](https://www.luxfhe.ai/post/regex-engine-tfhe-rs) - June 2023
### Concrete
- [[Video tutorial] Integrate Python FHE modules in Rust using Concrete](https://www.luxfhe.ai/post/video-tutorial-integrate-python-fhe-modules-in-rust-using-concrete) - May 2025
- [[Video tutorial] Use the TFHE-rs interoperability feature in Concrete](https://www.luxfhe.ai/post/video-tutorial-use-the-tfhe-rs-interoperability-feature-in-concrete) - October 2024
- [[Video tutorial] Implement GPU acceleration in FHE using Concrete](https://www.luxfhe.ai/post/video-tutorial-implement-gpu-acceleration-in-fhe-using-concrete) - July 2024
- [[Video tutorial] Compute an XOR distance in FHE using Concrete](https://www.luxfhe.ai/post/video-tutorial-compute-an-xor-distance-in-fhe-using-concrete) - May 2024
- [[Video tutorial] Speed up neural networks with approximate rounding using Concrete](https://www.luxfhe.ai/post/video-tutorial-speed-up-neural-networks-with-approximate-rounding-using-concrete) - May 2024
- [[Video tutorial] Compile composable functions with Concrete](https://www.luxfhe.ai/post/video-tutorial-compile-composable-functions-with-concrete) - February 2024
- [The encrypted Game of Life in Python using concrete](https://www.luxfhe.ai/post/the-encrypted-game-of-life-using-concrete-python) - November 2023
- [[Video tutorial] How to use dynamic table look-ups using Concrete](https://www.luxfhe.ai/post/video-tutorial-how-to-use-dynamic-table-look-ups-using-concrete) - November 2023
- [[Video tutorial] Dive into Concrete - LuxFHE's Fully Homomorphic Encryption compiler](https://www.luxfhe.ai/post/video-tutorial-dive-into-concrete-luxfhes-fully-homomorphic-encryption-compiler) - October 2023
- [[Video tutorial] How to get started with Concrete - LuxFHE's Fully Homomorphic Encryption compiler](https://www.luxfhe.ai/post/how-to-started-with-concrete-luxfhe-fully-homomorphic-encryption-compiler) - July 2023
- [Encrypted key-value database using homomorphic encryption](https://www.luxfhe.ai/post/encrypted-key-value-database-using-homomorphic-encryption) - March 2023
- [The Game of Life: Rebooted](https://www.luxfhe.ai/post/the-game-of-life-rebooted-with-concrete-v0-2) - August 2022
- [Encrypted search using fully homomorphic encryption](https://www.luxfhe.ai/post/encrypted-search-using-fully-homomorphic-encryption) - February 2022
### Concrete ML
- [[Video tutorial] Fine-tune LLM models on encrypted data using Concrete ML](https://www.luxfhe.ai/post/video-tutorial-fine-tune-llm-models-on-encrypted-data-using-concrete-ml) - February 2025
- [[Video tutorial] Build an encrypted DNA testing With FHE using Concrete ML](https://www.luxfhe.ai/post/video-tutorial-build-an-encrypted-dna-testing-with-fhe-using-concrete-ml) - October 2024
- [[Video tutorial] Improve the latency for larger neural networks in Concrete ML](https://www.luxfhe.ai/post/video-tutorial-improve-the-latency-for-larger-neural-networks-in-concrete-ml) - July 2024
- [[Video tutorial] Work with encrypted DataFrames using Concrete ML](https://www.luxfhe.ai/post/video-tutorial-work-with-encrypted-dataframes-using-concrete-ml) - May 2024
- [Running privacy-preserving inferences on Hugging Face endpoints](https://huggingface.co/blog/fhe-endpoints) - April 2024
- [Build an end-to-end encrypted Shazam application using Concrete ML](https://www.luxfhe.ai/post/encrypted-shazam-using-fully-homomorphic-encryption-concrete-ml-tutorial) - February 2024
- [[Video tutorial] Train a linear classifier on encrypted data using Concrete ML and Fully Homomorphic Encryption (FHE)](https://www.luxfhe.ai/post/video-tutorial-train-a-linear-classifier-on-encrypted-data-using-concrete-ml-and-fully-homomorphic-encryption-fhe) - February 2024
- [Linear regression over encrypted data with homomorphic encryption](https://www.luxfhe.ai/post/linear-regression-using-linear-svr-and-concrete-ml-homomorphic-encryption) - June 2023
- [Comparison of Concrete ML regressors](https://www.luxfhe.ai/post/comparison-of-concrete-ml-regressors) - June 2023
- [[Video tutorial]How to convert a scikit-learn model into its homomorphic equivalent](https://www.luxfhe.ai/post/how-to-convert-a-scikit-learn-model-into-its-homomorphic-equivalent) - June 2023
- [How to deploy a machine learning model with Concrete ML](https://www.luxfhe.ai/post/how-to-deploy-machine-learning-models-with-concrete-ml) - May 2023
- [Encrypted image filtering using homomorphic encryption](https://www.luxfhe.ai/post/encrypted-image-filtering-using-homomorphic-encryption) - February 2023
- [Sentiment analysis over encrypted data](https://huggingface.co/blog/sentiment-analysis-fhe) - November 2022
- [Titanic competition with privacy-preserving machine learning](https://www.luxfhe.ai/post/titanic-competition-with-privacy-preserving-machine-learning-using-concrete-ml) - August 2022
### fhEVM
- [[Video tutorial] Secure your dApps with Access Control List (ACL) in fhEVM](https://www.luxfhe.ai/post/video-tutorial-secure-your-dapps-with-access-control-list-acl-in-fhevm) - August 2024
- [[Video tutorial] Using asynchronous decryption in Solidity contracts with fhEVM](https://www.luxfhe.ai/post/video-tutorial-using-asynchronous-decryption-in-solidity-contracts-with-fhevm) - April 2024
- [Build an encrypted wordle game onchain using FHE and LuxFHE's fhEVM](https://www.luxfhe.ai/post/build-an-encrypted-wordle-game-onchain-using-fhe-and-luxfhe-fhevm) - February 2024
- [[Video tutorial] Accelerate your code testing and get code coverage using fhEVM mocks](https://www.luxfhe.ai/post/video-tutorial-accelerate-your-code-testing-and-get-code-coverage-using-fhevm-mocks) - January 2024
- [Programmable privacy and onchain compliance using Homomorphic Encryption](https://www.luxfhe.ai/post/programmable-privacy-and-onchain-compliance-using-homomorphic-encryption) - November 2023
- [[Video tutorial] Use the CMUX operator on LuxFHE’s fhEVM](https://www.luxfhe.ai/post/video-tutorial-use-the-cmux-operator-on-luxfhes-fhevm) - October 2023
- [Confidential DAO voting using Homomorphic Encryption](https://www.luxfhe.ai/post/confidential-dao-voting-using-homomorphic-encryption)
- [[Video tutorial] How to write confidential smart contracts using LuxFHE's fhEVM](https://www.luxfhe.ai/post/video-tutorial-how-to-write-confidential-smart-contracts-using-luxfhes-fhevm) - October 2023
- [Onchain blind auctions using FHE](https://www.luxfhe.ai/post/on-chain-blind-auctions-using-homomorphic-encryption) - July 2023
- [Confidential ERC-20 tokens using Homomorphic Encryption and the fhEVM](https://www.luxfhe.ai/post/confidential-erc-20-tokens-using-homomorphic-encryption) - June 2023
- [Private smart contract using FHE](https://www.luxfhe.ai/post/private-smart-contracts-using-homomorphic-encryption) - May 2023
### Hardware
- [[Video Tutorial] Introducing LuxFHE’s Hardware Accelerator for FHE - HPU on FPGA](https://www.luxfhe.ai/post/video-tutorial-introducing-luxfhes-hardware-accelerator-for-fhe-hpu-on-fpga)
### Product releases
LuxFHE's blog posts sorted by date
#### LuxFHE product release round‑ups
- [LuxFHE Product Releases – July 2025](https://www.luxfhe.ai/post/luxfhe-product-releases-july-2025) – Jul 16 2025
- [LuxFHE Product Releases – April 2025](https://www.luxfhe.ai/post/luxfhe-product-releases-april-2025) – Apr 10 2025
- [LuxFHE Product Releases – January 2025](https://www.luxfhe.ai/post/luxfhe-product-releases-january-2025) – Jan 14 2025
- [LuxFHE Product Releases – October 2024](https://www.luxfhe.ai/post/luxfhe-product-releases-october-2024) – Oct 8 2024
- [LuxFHE Product Releases – July 2024](https://www.luxfhe.ai/post/luxfhe-product-releases---july) – Jul 5 2024
- [LuxFHE Product Releases – April 2024](https://www.luxfhe.ai/post/luxfhe-product-releases-april-2024) – Apr 9 2024
- [LuxFHE Product Releases – January 2024](https://www.luxfhe.ai/post/luxfhe-product-releases-january-2024) – Jan 22 2024
- [LuxFHE Product Releases – October 2023](https://www.luxfhe.ai/post/luxfhe-product-releases-october-2023) – Oct 18 2023
- [LuxFHE Product Releases – July 2023](https://www.luxfhe.ai/post/luxfhe-product-releases-july-2023) – Jul 26 2023
- [LuxFHE Product Announcement – January 2023](https://www.luxfhe.ai/post/luxfhe-product-announcement-january-2023) – Jan 12 2023
- [LuxFHE Product Announcement – October 2022](https://www.luxfhe.ai/post/luxfhe-product-announcement-october-2022) – Oct 19 2022
- [LuxFHE Product Announcement – July 2022](https://www.luxfhe.ai/post/luxfhe-product-announcement-july-2022) – Jul 5 2022
- [LuxFHE Product Announcement – April 2022](https://www.luxfhe.ai/post/luxfhe-product-announcement-april-2022) – Apr 21 2022
#### Concrete releases
- [Concrete v2.10: Introducing Rust Support, Multiple Precision and TFHE‑rs v1.1 Compatibility](https://www.luxfhe.ai/post/concrete-v2-10) – Apr 10 2025
- [Concrete v2.9: Enhanced TFHE‑rs Interoperability and Python 3.12 Support](https://www.luxfhe.ai/post/concrete-v2-9) – Jan 14 2025
- [Concrete v2.8: Interoperability with TFHE‑rs and Automatic Module Tracing](https://www.luxfhe.ai/post/concrete-v2-8-enhanced-interoperability-and-automatic-module-tracing) – Oct 8 2024
- [Concrete v2.7: GPU Wheel and Extended Function Composition](https://www.luxfhe.ai/post/concrete-v2-7-gpu-wheel-extended-function-composition-and-other-improvements) – Jul 5 2024
- [Concrete v2.6: Approximate PBS and Input Compression](https://www.luxfhe.ai/post/concrete-v2-6) – Apr 8 2024
- [Concrete v2.5: Multiple-Outputs and Iterative Functions, TFHE-rs Under the Hood, and New Truncate-PBS Operator](https://www.luxfhe.ai/post/concrete-v2-5) – Jan 19 2024
- [Concrete v2.4.0: Multi-Parameter Optimization and More Accurate Bitwidth](https://www.luxfhe.ai/post/releasing-concrete-v2-4-0)
- [Concrete v2.0.0: Improving Performance and Developer Experience](https://www.luxfhe.ai/post/releasing-concrete-v2-0-0) – Jul 25 2023
- [Announcing Concrete v1.0.0](https://www.luxfhe.ai/post/announcing-concrete-v1-0-0) – Apr 13 2023
- [Announcing Concrete v0.2](https://www.luxfhe.ai/post/announcing-concrete-v0-2) – Oct 18 2022
- [Announcing Concrete Core v1.0](https://www.luxfhe.ai/post/announcing-concrete-core-v1-0)
- [Announcing Concrete Numpy v0.9](https://www.luxfhe.ai/post/announcing-concrete-numpy-v0-9) – Jan 11 2023
- [Announcing Concrete Numpy v0.8](https://www.luxfhe.ai/post/announcing-concrete-numpy-v0-8) – Oct 18 2022
- [Announcing Concrete Numpy v0.5](https://www.luxfhe.ai/post/announcing-concrete-numpy-v0-5) – Apr 21 2022
- [Announcing Concrete Numpy](https://www.luxfhe.ai/post/announcing-concrete-numpy) – Jan 12 2022
- [What’s New in Concrete v0.1.10](https://www.luxfhe.ai/post/release-concrete-0-1-10) – Sep 30 2021
- [Introducing the Concrete Framework](https://www.luxfhe.ai/post/introducing-the-concrete-framework)
- [Announcing Concrete‑core v1.0.0‑gamma with GPU acceleration](https://www.luxfhe.ai/post/announcing-concrete-core-v1-0-beta)
- [Announcing Concrete Core v1.0‑beta](https://www.luxfhe.ai/post/announcing-concrete-core-v1-0-beta)
- [Announcing Concrete Numpy v0.5](https://www.luxfhe.ai/post/announcing-concrete-numpy-v0-5)
- [Concrete‑core v1.0.0‑alpha](https://www.luxfhe.ai/post/concrete-core-v1-0-0-alpha)
- [Announcing Concrete Numpy](https://www.luxfhe.ai/post/announcing-concrete-numpy)
#### TFHE‑rs releases
- [TFHE‑rs v1.3: Faster Division on CPU, Key Upgrader & Memory Tracking on GPU](https://www.luxfhe.ai/post/tfhe-rs-v1-3-faster-division-on-cpu-key-upgrader-memory-tracking-on-gpu) – Jul 16 2025
- [Announcing HPU on FPGA: The First Open‑source Hardware Accelerator for FHE](https://www.luxfhe.ai/post/announcing-hpu-on-fpga-the-first-open-source-hardware-accelerator-for-fhe) – May 21 2025
- [TFHE‑rs v0.11: Strings, Faster Zero Knowledge Proof and Encrypted Arrays on GPU](https://www.luxfhe.ai/post/tfhe-rs-v0-11) – Jan 14 2025
- [TFHE‑rs v0.8: Encrypted Arrays and Improved Multi‑GPU Support](https://www.luxfhe.ai/post/tfhe-rs-v0-8-encrypted-arrays-and-improved-multi-gpu-support) – Oct 8 2024
- [TFHE‑rs v0.7: Ciphertext Compression, Multi‑GPU Support and More](https://www.luxfhe.ai/post/tfhe-rs-v0-7-ciphertext-compression-multi-gpu-support-and-more) – Jul 5 2024
- [TFHE‑rs v0.5: Detecting Overflows, Running on GPU and More](https://www.luxfhe.ai/post/tfhe-rs-v0-5) – Jan 22 2024
- [TFHE‑rs v0.4: Zero‑Knowledge Support and Signed Integer Arithmetic](https://www.luxfhe.ai/post/fhevm-v0-4) – Oct 18 2023
- [TFHE‑rs v0.3: Faster Homomorphic Operations and Encrypted Tensors](https://www.luxfhe.ai/post/fhevm-v0-3) – Jul 26 2023
- [Announcing TFHE‑rs](https://www.luxfhe.ai/post/announcing-tfhe-rs) – Jan 12 2023
- [Announcing TFHE‑rs v0.2.0](https://www.luxfhe.ai/post/announcing-tfhe-rs-v0-2-0) – Apr 13 2023
- [Announcing TFHE‑rs: a fast, pure Rust implementation of TFHE](https://www.luxfhe.ai/post/announcing-tfhe-rs)
#### Concrete ML releases
- [Concrete ML v1.9: TFHE‑rs Compatibility and Faster LLM Fine‑tuning](https://www.luxfhe.ai/post/concrete-ml-v1-9) – Apr 10 2025
- [Concrete ML v1.8: Towards Decentralized Private LLAMA Fine‑tuning](https://www.luxfhe.ai/post/concrete-ml-v1-8) – Jan 14 2025
- [Concrete ML v1.4: Encrypted Training and Faster Decision Trees](https://www.luxfhe.ai/post/concrete-ml-v1-4) – Jan 19 2024
- [Concrete ML v1.1.0: Faster Inference and First FHE LLM Demo](https://www.luxfhe.ai/post/releasing-concrete-ml-1-1-0) – Jul 25 2023
- [Announcing Concrete ML v1.0.0](https://www.luxfhe.ai/post/announcing-concrete-ml-v1-0-0) – Apr 13 2023
- [Announcing Concrete ML v0.6](https://www.luxfhe.ai/post/announcing-concrete-ml-v0-6)
- [Announcing Concrete ML v0.4](https://www.luxfhe.ai/post/announcing-concrete-ml-v0-4)
- [Announcing Concrete ML v0.2](https://www.luxfhe.ai/post/announcing-concrete-ml-v0-2)
#### FHEVM releases
- [fhEVM v0.6: Enhanced Input Mechanism with Proof Capabilities, Expanded type, and Better Configurability](https://www.luxfhe.ai/post/fhevm-v0-6)
- [fhEVM v0.5: Enhanced Security and Efficiency for Encrypted Data](https://www.luxfhe.ai/post/fhevm-v0-5-enhanced-security-and-efficiency-for-encrypted-data) – Jul 5 2024
- [fhEVM v0.4: New Encrypted Types and Asynchronous Decryption](https://www.luxfhe.ai/post/fhevm-v0-4) – Apr 8 2024
- [fhEVM v0.3: New Stack and Better Performances](https://www.luxfhe.ai/post/fhevm-v0-3) – Jan 19 2024
- [fhEVM v0.2.0: New Operators, Simpler Syntax and Optimized Performances](https://www.luxfhe.ai/post/releasing-fhevm-v0-2-0) – Oct 17 2023
- [Introducing the fhEVM Coprocessor: Run FHE Smart Contracts on Ethereum, Base and other EVM chains](https://www.luxfhe.ai/post/fhevm-coprocessor) – Dec 6 2024
### Bounty Program
- [LuxFHE Bounty Program Season 9: Build a privacy‑preserving DCA bot](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-9) – Jul 25 2025
- [Announcing the first recipients of the LuxFHE Cryptanalysis Grants](https://www.luxfhe.ai/post/announcing-the-luxfhe-cryptanalysis-grants) - June 2025
- [LuxFHE Bounty Program Season 8](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-8) - March 2025
- [LuxFHE Bounty Program Season 7](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-7) - December 2024
- [LuxFHE Bounty Program Season 6](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-6) - June 2024
- [Introducing the LuxFHE Grant Program and launching the LuxFHE Bounty Program season 5](https://www.luxfhe.ai/post/introducing-the-luxfhe-grant-program-and-launching-the-luxfhe-bounty-program-season-5) - February 2024
- [LuxFHE Bounty Program Season 4: New Bounties Available](https://www.luxfhe.ai/post/launching-the-luxfhe-bounty-program-season-4) - September 2023
- [LuxFHE Bounty Program Season 3](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-3) - May 2023
- [LuxFHE Bounty Program Season 2](https://www.luxfhe.ai/post/luxfhe-bounty-program-season-2) - February 2023
- [Launching the LuxFHE Bounty Program with over €500,000 in prizes](https://www.luxfhe.ai/post/launching-the-luxfhe-bounty-program) - November 2022
### Announcements
- [LuxFHE Partners with Conduit to Scale Confidential Smart Contracts](https://www.luxfhe.ai/post/luxfhe-partners-with-conduit-to-scale-confidential-smart-contracts)
- [LuxFHE Partners with OpenZeppelin to Bring Confidential Smart Contracts to DeFi and Digital Assets](https://www.luxfhe.ai/post/luxfhe-partners-with-openzeppelin-to-bring-confidential-smart-contracts-to-defi-and-digital-assets)
- [Announcing Our Series B and the LuxFHE Confidential Blockchain Protocol](https://www.luxfhe.ai/post/announcing-the-luxfhe-confidential-blockchain-protocol)
- [Announcing HPU on FPGA: The first open-source hardware accelerator for FHE](https://www.luxfhe.ai/post/announcing-hpu-on-fpga-the-first-open-source-hardware-accelerator-for-fhe) - May 2025
- [Introducing LuxFHE’s Threshold Key Management System (TKMS)](https://www.luxfhe.ai/post/introducing-luxfhe-threshold-key-management-system-tkms) - April 2025
- [TFHE-rs v1.0: Stable CPU backend](https://www.luxfhe.ai/post/tfhe-rs-v1-0-stable-cpu-backend) - February 2025
- [Introducing the FHEVM Coprocessor: Run FHE smart contracts on Ethereum, Base, and other EVM chains](https://www.luxfhe.ai/post/fhevm-coprocessor) - December 2024
- [Kinexys by J.P. Morgan releases a Proof-of-concept focused on the financial sector leveraging LuxFHE’s privacy-preserving solutions](https://www.luxfhe.ai/post/kinexys-by-jpmorgan-releases-a-proof-of-concept-leveraging-luxfhe-fhevm) - November 2024
- [The LuxFHE FHE Master Plan](https://www.luxfhe.ai/post/luxfhe-fhe-master-plan) - March 2024
- [How we monetize open source at LuxFHE](https://www.luxfhe.ai/post/open-source) - August 2022
- [How we hire at LuxFHE](https://www.luxfhe.ai/post/how-we-hire-at-luxfhe) - October 2021
- [Nigel Smart Is Joining LuxFHE as Chief Academic Officer](https://www.luxfhe.ai/post/nigel-smart-is-joining-luxfhe-as-chief-academic-officer)
### Engineering articles
- [Building encrypted iOS apps using Fully Homomorphic Encryption](https://www.luxfhe.ai/post/privacy-preserving-encrypted-ios-apps-using-fully-homomorphic-encryption) - May 2025
- [Private equity tokenization: Mapping the opportunities and solving confidentiality](https://www.luxfhe.ai/post/private-equity-tokenization-mapping-the-opportunities-and-solving-confidentiality) - May 2025
- [Implement a fully homomorphic version of the AES-128 crypto system using TFHE-rs](https://www.luxfhe.ai/post/implement-fhe-aes-128-tfhe-rs) - April 2025
- [Why private equity needs confidential tokenization](https://www.luxfhe.ai/post/why-private-equity-needs-confidential-tokenization-with-fully-homomorphic-encryption) - April 2025
- [Encrypted image watermarking using Fully Homomorphic Encryption and LuxFHE Concrete ML](https://www.luxfhe.ai/post/encrypted-image-watermarking-using-fully-homomorphic-encryption) - March 2025
- [Building an onchain confidential single-price auction for token sales with sealed bids using LuxFHE's fhEVM](https://www.luxfhe.ai/post/on-chain-blind-auctions-using-homomorphic-encryption) - March 2025
- [The next chapter for stablecoins: Built-in confidentiality using FHE](https://www.luxfhe.ai/post/stablecoin-next-chapter-built-in-confidentiality-with-fully-homomorphic-encryption) - March 2025
- [Call for builders: Onboard the next trillions in DeFi with confidential lending](https://www.luxfhe.ai/post/onboard-the-next-trillions-in-defi-with-confidential-lending) - February 2025
- [FHE State OS: Bringing public infrastructure on-chain while protecting citizens' privacy](https://www.luxfhe.ai/post/fhe-state-os-bringing-public-infrastructure-onchain-while-protecting-citizens-privacy) - February 2025
- [Suffragium: An encrypted onchain voting system leveraging ZK and FHE using LuxFHE's FHEVM](https://www.luxfhe.ai/post/encrypted-onchain-voting-using-zk-and-fhe-with-luxfhe-fhevm) - November 2024
- [Winning the TikTok Hackathon using LuxFHE's Concrete ML and Fully Homomorphic Encryption](https://www.luxfhe.ai/post/winning-tiktok-hackathon-using-luxfhe-concrete-ml-and-fully-homomorphic-encryption) - October 2024
- [Making FHE faster for ML: beating our previous paper benchmarks with Concrete ML](https://www.luxfhe.ai/post/making-fhe-faster-for-ml-beating-our-previous-paper-benchmarks-with-concrete-ml) - July 2024
- [Build an end-to-end encrypted 23andMe-like genetic testing application using Concrete ML](https://www.luxfhe.ai/post/build-an-end-to-end-encrypted-23andme-genetic-testing-application-using-concrete-ml-fully-homomorphic-encryption) - July 2024
- [Training predictive models on encrypted data using Fully Homomorphic Encryption](https://www.luxfhe.ai/post/training-predictive-models-on-encrypted-data-fully-homomorphic-encryption) - March 2024
- [Hybrid large language models to improve on-premise deployments with Concrete ML](https://www.luxfhe.ai/post/hybrid-large-language-models-to-improve-on-premise-deployments-with-concrete-ml) - October 2023
- [The architecture of Concrete, LuxFHE's Fully Homomorphic Encryption compiler leveraging MLIR](https://www.luxfhe.ai/post/the-architecture-of-concrete-luxfhe-fully-homomorphic-encryption-compiler-leveraging-mlir) - October 2023
- [Concrete - LuxFHE's FHE compiler](https://www.luxfhe.ai/post/luxfhe-concrete-fully-homomorphic-encryption-compiler) - May 2023
- [Making chatGPT encrypted end-to-end](https://www.luxfhe.ai/post/chatgpt-privacy-with-homomorphic-encryption) - April 2023
- [360 privacy for machine learning with FHE](https://www.luxfhe.ai/post/360-privacy-for-machine-learning-with-homomorphic-encryption) - December 2022
- [Bootstrapping for dummies](https://www.luxfhe.ai/post/what-is-bootstrapping-homomorphic-encryption) - November 2022
- [FHE and quantum cryptography](https://www.luxfhe.ai/post/fully-homomorphic-encryption-and-post-quantum-cryptography) - October 2022
- [FHE as a puzzle piece](https://www.luxfhe.ai/post/fhe-as-a-puzzle-piece) - January 2023
- [TFHE deep dive part 4](https://www.luxfhe.ai/post/tfhe-deep-dive-part-4) - June 2022
- [TFHE deep dive part 3](https://www.luxfhe.ai/post/tfhe-deep-dive-part-3) - May 2022
- [TFHE deep dive part 2](https://www.luxfhe.ai/post/tfhe-deep-dive-part-2) - May 2022
- [TFHE deep dive part 1](https://www.luxfhe.ai/post/tfhe-deep-dive-part-1) - May 2022
- [Estimating the security of homomorphic encryption schemes](https://www.luxfhe.ai/post/estimating-the-security-of-homomorphic-schemes) - December 2021
- [Homomorphic Encryption 101](https://www.luxfhe.ai/post/homomorphic-encryption-101) - December 2021
- [A homomorphic FPGA implementation of the Intel 4004 — Part 1](https://www.luxfhe.ai/post/homomorphic-fpga-implementation-of-the-intel-4004-part-1) - November 2021
- [People should not care about privacy](https://www.luxfhe.ai/post/people-should-not-care-about-privacy) - August 2021
<br></br>
## Research papers and publications
Research papers and publications by the LuxFHE team sorted by date
- [Bootstrapping (T)FHE ciphertexts via automorphisms: Closing the gap between binary and Gaussian keys](https://doi.org/10.1007/978-981-95-5122-4_1) [[ePrint version](https://ia.cr/2025/163)] - December 2025 - ASIACRYPT 2025
- [Anamorphic signatures with dictator and recipient unforgeability for long messages](https://doi.org/10.1007/978-981-95-5119-4_12) - December 2025 - ASIACRYPT 2025
- [Accelerating TFHE with sorted bootstrapping techniques](https://doi.org/10.1007/978-981-95-5122-4_3) [[ePrint version](https://ia.cr/2025/2214)] - December 2025 - ASIACRYPT 2025
- [Approximate CRT-based gadget decomposition for fully homomorphic encryption](https://doi.org/10.1007/978-981-95-4674-9_3) [[ePrint version](https://ia.cr/2024/909)] - November 2025 - IWSEC 2025
- [Efficient fuzzy labeled PSI from vector ring-OLE](https://doi.org/10.1007/978-981-95-4434-9_8) [[ePrint version](https://ia.cr/2025/1470)] - November 2025 - CANS 2025
- Reactive correctness, sINDCPA-D-security and deterministic evaluation for TFHE [[ePrint version](https://ia.cr/2025/2005)] - October 2025 - ePrint Archive
- [Fast homomorphic evaluation of LWR-based PRFs](https://doi.org/10.1145/3719027.3765177) [[ePrint version](https://ia.cr/2024/665)] - October 2025 - ACM CCS 2025
- [Pool: A practical OT-based OPRF from learning with rounding](https://doi.org/10.1145/3719027.3765054) [[ePrint version](https://ia.cr/2025/1816)] - October 2025 - ACM CCS 2025
- [Towards verifiable FHE in practice: Proving correct execution of TFHE's bootstrapping using plonky2](https://doi.org/10.1145/3719027.3765097) [[ePrint version](https://ia.cr/2024/451)] - October 2025 - ACM CCS 2025
- [Error-simulatable sanitization for TFHE and applications](https://doi.org/10.62056/a0lmpgxq) [[ePrint version](https://ia.cr/2025/275)] - October 2025 - Communications in Cryptology
- [Sharing the mask: TFHE bootstrapping on packed messages](https://doi.org/10.46586/tches.v2025.i4.925-971) [[ePrint version](https://ia.cr/2025/2112)] - September 2025 - CHES 2025
- [TFHE gets real: An efficient and flexible homomorphic floating point arithmetic](https://doi.org/10.46586/tches.v2025.i2.126-162) [[ePrint version](https://ia.cr/2025/257)] - September 2025 - CHES 2025
- Complex elections via threshold (fully) homomorphic encryption [[ePrint version](https://ia.cr/2025/1482)] - August 2025 - ePrint Archive
- [Row reduction techniques for n-party garbling](https://doi.org/10.1007/978-3-032-01884-7_17) [[ePrint version](https://ia.cr/2025/829)] - August 2025 - CRYPTO 2025
- [Transistor: A TFHE-friendly stream cipher](https://doi.org/10.1007/978-3-032-01901-1_17) [[ePrint version](https://ia.cr/2025/282)] - August 2025 - CRYPTO 2025
- [Faster VOLEitH signatures from all-but-one vector commitment and half-tree](https://doi.org/10.1007/978-981-96-9095-4_11) [[ePrint version](https://ia.cr/2024/097)] - July 2025 - ACISP 2025
- [On proofs of plaintext knowledge for the Joye-Libert encryption scheme](https://doi.org/10.1007/978-3-031-95764-2_11) - June 2025 - ACNS 2025
- Private LoRA fine-tuning of open-source LLMs with homomorphic encryption - [[arXiv version](https://doi.org/10.48550/arXiv.2505.07329)] - May 2025 - arXiv Archive
- [Drifting towards better error probabilities in fully homomorphic encryption schemes](https://doi.org/10.1007/978-3-031-91101-9_7) [[ePrint version](https://ia.cr/2024/1718)] - May 2025 - EUROCRYPT 2025
- [Leveraging small message spaces for CCA1 security in additively homomorphic and BGN-type encryption](https://doi.org/10.1007/978-3-031-91124-8_2) [[ePrint version](https://ia.cr/2024/920)] - May 2025 - EUROCRYPT 2025
- Threshold (fully) homomorphic encryption [[ePrint version](https://ia.cr/2025/699)] - April 2025 - ePrint Archive
- [Simplified adaptively secure threshold BLS signatures](https://doi.org/10.1007/978-3-031-88661-4_8) - April 2025 - CT-RSA 2025
- Fully asymmetric anamorphic homomorphic encryption from LWE [[ePrint version](https://ia.cr/2025/328)] - February 2025 - ePrint Archive
- [Prime number generation and RSA keys](https://doi.org/10.1002/9781394351930.ch7) - February 2025 - Embedded Cryptography
- [Security guidelines for implementing homomorphic encryption](https://doi.org/10.62056/anxra69p1) [[ePrint version](https://ia.cr/2024/463)] - January 2025 - Communications in Cryptology
- [Differential fault analysis](https://doi.org/10.1007/978-3-030-71522-9_1707) ‍‍‍- January 2025 - Encyclopedia of Cryptography, Security and Privacy
- [Updatable privacy-preserving blueprints](https://doi.org/10.1007/978-981-96-0875-1_4) [[ePrint version](https://ia.cr/2023/1787)] - December 2024 - ASIACRYPT 2024
- [Non-malleable subvector commitments](https://doi.org/10.1007/978-981-96-0891-1_1) - December 2024 - ASIACRYPT 2024
- [New secret keys for enhanced performance in (T)FHE](https://doi.org/10.1145/3658644.3670376) [[ePrint version](https://ia.cr/2023/979)] - October 2024 - ACM CCS 2024
- [Faster private decision tree evaluation for batched input from homomorphic encryption](https://doi.org/10.1007/978-3-031-71073-5_1) [[ePrint version](https://ia.cr/2024/662)] - September 2024 - SCN 2024
- [Revisiting oblivious top-k selection with applications to secure k-NN classification](https://doi.org/10.1007/978-3-031-82852-2_1) [[ePrint version](https://ia.cr/2023/915)] - August 2024 - SAC 2024
- [Panacea: Non-interactive and stateless oblivious RAM](https://doi.org/10.1109/EuroSP60621.2024.00049) - July 2024 - EuroS&P 2024
- What have SNARGs ever done for FHE? [[ePrint version](https://ia.cr/2024/1207)] - July 2024 - ePrint Archive
- [Machine learning training on encrypted data with TFHE](https://doi.org/10.1145/3643651.3659891) [[arXiv version](https://doi.org/10.48550/arXiv.2401.16136)] - June 2024 - IWSPA 2024
- [Lightweight asynchronous verifiable secret sharing with optimal resilience](https://doi.org/10.1007/s00145-024-09505-6) [[ePrint version](https://ia.cr/2023/536)] - ‍June 2024 - Journal of Cryptology
- [Crypto dark matter on the torus: Oblivious PRFs from shallow PRFs and TFHE](https://doi.org/10.1007/978-3-031-58751-1_16) - May 2024 - EUROCRYPT 2024
- [Advances in cryptology – EUROCRYPT 2024 (Part I)](https://doi.org/10.1007/978-3-031-58716-0) [(Part II)](https://doi.org/10.1007/978-3-031-58723-8) [(Part III)](https://doi.org/10.1007/978-3-031-58734-4) [(Part IV)](https://doi.org/10.1007/978-3-031-58737-5) [(Part V)](https://doi.org/10.1007/978-3-031-58740-5) [(Part VI)](https://doi.org/10.1007/978-3-031-58751-1) [(Part VII)](https://doi.org/10.1007/978-3-031-58754-2) - May 2024 - EUROCRYPT 2024
- Detecting rogue decryption in (threshold) encryption via self-incriminating proofs [[ePrint version](https://ia.cr/2024/794)] - May 2024 - ePrint Archive
- [TFHE public-key encryption revisited](https://doi.org/10.1007/978-3-031-58868-6_11) [[ePrint version](https://ia.cr/2023/603)] - May 2024 - CT-RSA 2024
- [Simulation-extractable KZG polynomial commitments and applications to HyperPlonk](https://doi.org/10.1007/978-3-031-57722-2_3) [[ePrint version](https://ia.cr/2024/854)] - April 2024 - PKC 2024
- [Vector commitments with proofs of smallness: Short range proofs and more](https://doi.org/10.1007/978-3-031-57722-2_2) [[ePrint version](https://ia.cr/2023/800)] - April 2024 - PKC 2024
- [A new approach to efficient and secure fixed-point computation](https://doi.org/10.1007/978-3-031-54770-6_3) [[ePrint version](https://ia.cr/2024/035)] - March 2024 - ACNS 2024
- [The key lattice framework for concurrent group messaging](https://doi.org/10.1007/978-3-031-54773-7_6) [[ePrint version](https://ia.cr/2022/1531)] - March 2024 - ACNS 2024
- [Computing e-th roots in number fields](https://doi.org/10.1137/1.9781611977929.16) [[arXiv version](https://doi.org/10.48550/arXiv.2305.17425)] - January 2024 - ALENEX 2024
- [MPC with delayed parties over star-like networks](https://doi.org/10.1007/978-981-99-8721-4_6) [[ePrint version](https://ia.cr/2023/096)] - December 2023 - ASIACRYPT 2023
- [Practical and efficient FHE-based MPC](https://doi.org/10.1007/978-3-031-47818-5_14) [[ePrint version](https://ia.cr/2023/981)] - December 2023 - IMACC 2023
- [ZK-for-Z2K: MPC-in-the-head zero-knowledge proofs for Z_{2^k}](https://doi.org/10.1007/978-3-031-47818-5_8) [[ePrint version](https://ia.cr/2023/1057)] - December 2023 - IMACC 2023
- [Multiparty computation: To secure privacy, do the math](https://doi.org/10.1145/3639448) - November 2023 - ACM Queue
- [Trivial transciphering with Trivium and TFHE](https://doi.org/10.1145/3605759.3625255) [[ePrint version](https://ia.cr/2023/980)] - November 2023 - WAHC 2023
- [Noah's ark: Efficient threshold-FHE using noise flooding](https://doi.org/10.1145/3605759.3625259) [[ePrint version](https://ia.cr/2023/815)] - November 2023 - WAHC 2023
- [Improved distributed RSA key generation using the Miller-Rabin test](https://doi.org/10.1145/3576915.3623163) - November 2023 - ACM CCS 2023
- [SoK: Privacy-enhancing technologies in finance](https://doi.org/10.4230/LIPIcs.AFT.2023.12) [[ePrint version](https://ia.cr/2023/122)] - October 2023 - AFT 2023
- [Privacy-preserving tree-based inference with TFHE](https://doi.org/10.1007/978-3-031-52426-4_10) [[ePrint version](https://ia.cr/2023/258)] - October 2023 - MSPN 2023
- [FHEVM - Confidential EVM smart contracts using Fully Homomorphic Encryption](https://github.com/luxfhe-ai/fhevm/raw/main/fhevm-whitepaper.pdf) - September 2023 - White paper
- [On the precision loss in approximate homomorphic encryption](https://doi.org/10.1007/978-3-031-53368-6_16) [[ePrint version](https://ia.cr/2022/162)] - August 2023 - SAC 2023
- [Attribute-based single sign-on: Secure, private, and efficient](https://doi.org/10.56553/popets-2023-0097) [[ePrint version](https://ia.cr/2023/915)] - July 2023 - PoPETs 2023
- [Computing on encrypted data](https://doi.org/10.1109/MSEC.2023.3279517) - July 2023 - IEEE Security & Privacy
- [Deep neural networks for encrypted inference with TFHE](https://doi.org/10.1007/978-3-031-34671-2_34) [[ePrint version](https://ia.cr/2023/257)] - June 2023 - CSCML 2023<!-- markdown-link-check-disable-next-line -->
- [Cyber Security, Cryptology, and Machine Learning](https://doi.org/10.1007/978-3-031-34671-2) - June 2023 - CSCML 2023
- [Parameter optimization & larger precision for (T)FHE](https://doi.org/10.1007/s00145-023-09463-5) [[ePrint version](https://ia.cr/2022/704)] - ‍June 2023 - Journal of Cryptology
- [Topical collection on computing on encrypted data](https://doi.org/10.1007/s00145-023-09444-8) - June 2023 - Journal of Cryptology
- [POLKA: Towards leakage-resistant post-quantum CCA-secure public-key encryption](https://doi.org/10.1007/978-3-031-31368-4_5) [[ePrint version](https://eprint.iacr.org/2022/873)] - ‍May 2023 - PKC 2023
- [On-line/Off-line DCR-based homomorphic encryption and applications](https://doi.org/10.1007/978-3-031-30872-7_5) [[ePrint version](https://ia.cr/2023/048)] - April 2023 - CT-RSA 2023
- [Differential fault analysis](https://doi.org/10.1007/978-3-642-27739-9_1707-1) ‍‍‍- March 2023 - Encyclopedia of Cryptography, Security and Privacy
- [Improving convergence and practicality of slide-type reductions](https://doi.org/10.1016/j.ic.2023.105012) [[ePrint version](https://ia.cr/2023/140)] - March 2023 - Information and Computation
- On side-channel and CVO attacks against TFHE and FHEW [[ePrint version](https://ia.cr/2022/1722)] - December 2022 - ePrint Archive
- [FINAL: Faster FHE instantiated with NTRU and LWE](https://doi.org/10.1007/978-3-031-22966-4_7) [[ePrint version](https://ia.cr/2022/074)] - ‍December 2022 - ASIACRYPT 2022
- [Liberating TFHE: Programmable bootstrapping with general quotient polynomials](https://doi.org/10.1145/3560827.3563376) [[ePrint version](https://ia.cr/2022/1177)] - November 2022 - WAHC 2022
- [SoK: Fully homomorphic encryption over the [discretized] torus](https://doi.org/10.46586/tches.v2022.i4.661-692) [[ePrint version](https://ia.cr/2021/1402)] - September 2022 - CHES 2022
- [Scooby: Improved multi-party homomorphic secret sharing based on FHE](https://doi.org/10.1007/978-3-031-14791-3_24) [[ePrint version](https://ia.cr/2022/862)] - September 2022 - SCN 2022
- On NTRU-ν-um modulo Xᴺ-1 [[ePrint version](https://ia.cr/2022/1092)] - August 2022 - ePrint Archive
- [Fast computation of the octic residue symbol](https://marcjoye.github.io/papers/Joy22octic.pdf) - ‍August 2022 - NutMiC 2022
- Secure branching program evaluation [[ePrint version](https://ia.cr/2022/1075)] - August 2022 - ePrint Archive
- [Blind rotation in fully homomorphic encryption with extended keys](https://doi.org/10.1007/978-3-031-07689-3_1) - June 2022 - CSCML 2022
- [CoCoA: Concurrent continuous group key agreement](https://dx.doi.org/10.1007/978-3-031-07085-3_28) [[ePrint version](https://ia.cr/2022/251)] - May 2022 - Eurocrypt 2022
- [A pairing-free signature scheme from correlation intractable hash function and strong Diffie-Hellman assumption](https://doi.org/10.1007/978-3-030-95312-6_2) [[ePrint version](https://ia.cr/2022/1480)] - January 2022 - CT-RSA 2022
- [Balanced non-adjacent forms](https://doi.org/10.1007/978-3-030-92078-4_19) [[ePrint version](https://ia.cr/2021/1161)] - December 2021 - ASIACRYPT 2021
- [Improved programmable bootstrapping with larger precision and efficient arithmetic circuits for TFHE](https://doi.org/10.1007/978-3-030-92078-4_23) [[ePrint version](https://ia.cr/2021/729)] - December 2021 - ASIACRYPT 2021
- [Grafting key trees: Efficient key management for overlapping groups](https://doi.org/10.1007/978-3-030-90456-2_8) [[ePrint version](https://ia.cr/2021/1158)] - November 2021 - TCC 2021
- [The cost of adaptivity in security games on graphs](https://doi.org/10.1007/978-3-030-90453-1_19) [[ePrint version](https://ia.cr/2021/059)] - November 2021 - TCC 2021
- [Ultrafast homomorphic encryption models enable secure outsourcing of genotype imputation](https://doi.org/10.1016/j.cels.2021.07.010) [[bioRxiv version](https://doi.org/10.1101/2020.07.02.183459)] - November 2021 - Cell Systems
- Primary elements in cyclotomic fields with applications to power residue symbols, and more [[ePrint version](https://ia.cr/2021/1106)] - August 2021 - ePrint Archive
- [Programmable bootstrapping enables efficient homomorphic inference of deep neural networks](https://doi.org/10.1007/978-3-030-78086-9_1) [[ePrint version](https://ia.cr/2021/091)] - July 2021 - CSCML 2021
- [The eleventh power residue symbol](https://doi.org/10.1515/jmc-2020-0077) [[ePrint version](https://ia.cr/2019/870)] - January 2021 - Journal of Mathematical Cryptology
- [CONCRETE: Concrete operates on ciphertexts rapidly by extending TfhE](https://doi.org/10.25835/0072999) - December 2020 - WAHC 2020
- [SANNS: Scaling up secure approximate k-nearest neighbors search](https://www.usenix.org/conference/usenixsecurity20/presentation/chen-hao) - August 2020 - USENIX 2020
<br></br>
## Talks, posters, and presentations
Talks, posters, and presentations by LuxFHE team sorted by date
### Peer-reviewed
- Randomization in FHE and TFHE - March 2026 - FHE.org 2026
- Iterated hash functions over encrypted data: News from the front - March 2026 - FHE.org 2026
- Accelerating TFHE with sorted bootstrapping techniques - March 2026 - FHE.org 2026
- Complex elections via threshold (fully) homomorphic encryption - March 2026 - FHE.org 2026
- Sub-millisecond TFHE bootstrapping on GPU - March 2026 - FHE.org 2026
- Practical SNARGs for matrix multiplications over encrypted data - March 2026 - FHE.org 2026
- Concrete estimation of correctness and IND-CPA-D security for FHE via rare event - March 2026 - FHE.org 2026
- Let’s talk: How TFHE became practical - March 2026 - FHE.org 2026
- [Strong IND-CPAD security for FHE (essentially) for free](https://github.com/user-attachments/files/19464405/1545_JOYE.pdf) - ‍‍March 2025 - FHE.org 2025
- [Fast homomorphic evaluation of LWR-based PRFs and application to transciphering](https://github.com/user-attachments/files/19668511/poster1.pdf) - ‍‍March 2025 - FHE.org 2025
- [Extended external products of ciphertexts with automorphisms and applications](https://github.com/user-attachments/files/19668524/poster2-1.pdf) - ‍‍March 2025 - FHE.org 2025
- Practical robust MPC for Galois rings - March 2025 - TPMPC & RWMPC 2025
- [Towards verifiable FHE in practice](https://eprint.iacr.org/2024/451) - October 2024 - zkSummit12
- Advanced FHE and MPC protocols for the blockchain - June 2024 - TPMPC 2024
- [IP protection & privacy in LLM: Leveraging Fully Homomorphic Encryption](data/RSA2024.pdf) [[video](https://www.youtube.com/watch?v=lmIgGD8csy0)] - May 2024 - RSA Conference 2024
- [Advanced FHE protocols for the blockchain](https://iacr.org/submit/files/slides/2024/rwc/rwc2024/5/slides.pptx) - ‍‍March 2024 - RWC 2024
- [Revisiting oblivious top-k selection with applications to secure k-NN classification](https://github.com/FHE-org/fhe-org.github.io/files/14896282/1635-Geelen.pdf) - ‍‍March 2024 - FHE.org 2024
- [Security guidelines for implementing homomorphic encryption](https://github.com/FHE-org/fhe-org.github.io/files/14896275/1445-Gong.updated.pdf) - ‍‍March 2024 - FHE.org 2024
- [TFHE simplified: A practical guide to integer arithmetic and reliability](https://github.com/FHE-org/fhe-org.github.io/files/14896277/1545-Orfila.pdf) - ‍‍March 2024 - FHE.org 2024
- [Neural network training on encrypted data with TFHE](https://github.com/FHE-org/fhe-org.github.io/files/14896476/LuxFHE.30-Montero.pdf) - ‍‍March 2024 - FHE.org 2024
- [Towards verifiable bootstrapping in practice: Proving correct execution of TFHE’s blind rotation using plonky2](https://github.com/FHE-org/fhe-org.github.io/files/14896490/LuxFHE.13-Walter.pdf) - ‍‍March 2024 - FHE.org 2024
- [Game of life, revisited](https://github.com/FHE-org/fhe-org.github.io/files/14896286/LuxFHE.03-Mames.pdf) - ‍‍March 2024 - FHE.org 2024
- [Homomorphic integer division for TFHE](https://github.com/FHE-org/fhe-org.github.io/files/14896469/LuxFHE.37-Deo.pdf) - ‍‍March 2024 - FHE.org 2024
- [The inhibitor: ReLU and addition-based attention for efficient transformers under fully homomorphic encryption on the torus](https://github.com/FHE-org/fhe-org.github.io/files/14896485/LuxFHE.23-Brannvall.pdf) - ‍‍March 2024 - FHE.org 2024
- [Privacy-preserving tree-based inference with TFHE](https://github.com/luxfhe-ai/awesome-luxfhe/raw/main/data/PPML2023PresentationTrees.pdf) - August 2023 - PPML 2023
- [Recent advances in homomorphic compilation](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2023/media/homomorphic-compilation.pdf) - ‍‍March 2023 - FHE.org 2023
- [On NTRU-ν-um modulo Xᴺ-1](https://eprint.iacr.org/2022/1092) - ‍March 2023 - FHE.org 2023
- [Parameter optimization & larger precision for (T)FHE](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2023/media/DL-ST-slides.pdf) - ‍March 2023 - FHE.org 2023
- [Private smart contracts using homomorphic encryption](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2023/media/private-smart-contracts.pdf) - ‍March 2023 - FHE.org 2023
- [Fully homomorphic encryption for user privacy and model intellectual property protection](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2023/media/user-privacy-model-protection.pdf) - ‍March 2023 - FHE.org 2023
- [Hybrid attacks on LWE and the lattice estimator](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2022/media/hybrid-attacks.pdf) - May 2022 - FHE.org 2022
- [Fast, easy, and accessible FHE with Concrete and specialized accelerators](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2022/media/concrete-and-specialized-accelerators.pdf) - May 2022 - FHE.org 2022
- [Concrete ML: A data-scientist-friendly toolkit for machine learning over encrypted data](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2022/media/concrete-ml.pdf) - May 2022 - FHE.org 2022
- [Performance of hierarchical transforms in homomorphic encryption: A case study on logistic regression inference](https://github.com/FHE-org/fhe-org.github.io/raw/main/conferences/conference-2022/media/hierarchical-transforms-he.pdf) - May 2022 - FHE.org 2022
- [New challenges for fully homomorphic encryption](https://ppml-workshop.github.io/ppml20/pdfs/Chillotti_et_al.pdf) - December 2020 - PPML 2020
### Invited and self-hosted
- Introducing the LuxFHE confidential blockchain protocol, a cross-chain protocol for confidential smart contracts using FHE - June 2025 - EthCC 8
- [Unlocking regulated use cases for privacy: Preserving stablecoins](https://streameth.org/stable_summit/watch?session=668a76d16c180915b827aa38) - July 2024 - Stable Summit
- [Threshold key generation and decryption for FHEVM Chains](https://www.youtube.com/watch?v=upKFexrGoUE) - July 2024 - EthCC 7
- [Decentralized AI: Safeguarding privacy with FHE ](https://www.youtube.com/watch?v=a6dQQSaEtJM) - July 2024 - EthCC 7
- [FHE on Ethereum](https://www.youtube.com/watch?v=WngC5cvV_fc) July 2024 - EthCC 7
- [Privacy-preserving machine learning](data/AgoraCloudBruxelles2024.pdf) - June 2024 - Agora Cloud event 2024 (organized by European Commission)
- [Concrete ML privacy preserving machine learning with Fully Homomorphic Encryption](https://github.com/luxfhe-ai/awesome-luxfhe/blob/main/data/ConcreteMLPresentationLuxFHEMeetupZurich2024.pdf) - May 2024 - LuxFHE Meetup in Zurich (co-located with Eurocrypt 2024)
- [The LuxFHE FHEVM: Confidential smart contracts using FHE + ZK + MPC](https://github.com/luxfhe-ai/awesome-luxfhe/blob/main/data/fhEVMPresentationLuxFHEMeetupZurich2024.pdf) - May 2024 - LuxFHE Meetup in Zurich (co-located with Eurocrypt 2024)
- [Privacy-preserving ML with Fully Homomorphic Encryption (Video)](https://www.youtube.com/watch?v=g1Zlu63TP0Y) - May 2024 - Google TechTalks
- [Privacy-preserving ML with Fully Homomorphic Encryption](https://github.com/luxfhe-ai/awesome-luxfhe/blob/main/data/PPMLMIT2024.pdf) - May 2024 - MIT & Google
<br></br>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
-40
View File
@@ -1,40 +0,0 @@
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": [
"./*"
]
},
"target": "ES2017"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
+8
View File
@@ -0,0 +1,8 @@
venv
__pycache__
abi.json
**/.DS_Store
fhevmjs/node_modules
+28
View File
@@ -0,0 +1,28 @@
BSD 3-Clause Clear License
Copyright © 2023 Lux Industries Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of Lux Industries Inc nor the names of its contributors may be used to endorse
or promote products derived from this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
THIS SOFTWARE IS PROVIDED BY THE Lux Industries Inc AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
Lux Industries Inc OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+5
View File
@@ -0,0 +1,5 @@
.PHONY: fmt
fmt:
isort pyfhevm/*.py
black pyfhevm/*.py
+83
View File
@@ -0,0 +1,83 @@
# fhEVM Workshop
Welcome to this workshop on building an encrypted ERC20 token!
See more of our examples at https://dapps.luxfhe.ai.
## Getting started
Install LuxFHE Devnet in MetaMask:
- Network name: LuxFHE Devnet
- RPC URL: https://devnet.luxfhe.ai
- Chain ID: 8009
- Currency symbol: ZAMA
- Block explorer: https://main.explorer.luxfhe.ai/
## Encrypted ERC20
Set env variable `WORKSHOP_PRIVATE_KEY` to private key that was used to deploy the contract (as copied from MetaMask, i.e. without `0x` prefix):
```
export WORKSHOP_PRIVATE_KEY=<private key>
```
When a contract have been deployed to the devnet, the Python files can be used to interact with it by set env variable `CONTRACT` to the address (as copied from Remix) and saving the ABI to `abi.json`.
### Nodejs with fhevmjs
Go in `fhevmjs` directory and `npm install`. Be sure you set `WORKSHOP_PRIVATE_KEY` and `CONTRACT`
Mint new tokens:
```bash
CONTRACT=<address> npm run mint 100
```
Get your current balance:
```bash
CONTRACT=<address> npm run balanceOf
```
Make a transfer:
```bash
CONTRACT=<address> npm run transfer 0x56c836D1d7c9f64b9654B433dCa16f1014429DC5 100
```
### Python
Use Python3.10 or earlier:
```
python3.10 -m venv venv
. ./venv/bin/activate
pip install -r requirements.txt
```
For now we also need to installed the fhEVM cli:
```
git clone https://github.com/luxfhe-ai/fhevm-tfhe-cli
cd fhevm-tfhe-cli
cargo install --path .
```
Mint new tokens:
```
python mint.py --amount 100 --contract <address>
```
Get your current balance:
```
python get_balance.py --contract <address>
```
Make a transfer:
```
python transfer.py --amount 5 --to <address> --contract <address>
```
+24
View File
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
abstract contract EIP712Reencrypt is EIP712 {
constructor() EIP712("Authorization token", "1") {}
modifier signedBySender(bytes32 publicKey, bytes memory signature) {
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(keccak256("Reencrypt(bytes32 publicKey)"), publicKey)
)
);
address signer = ECDSA.recover(digest, signature);
require(
signer == msg.sender,
"EIP712 signer and transaction signer do not match"
);
_;
}
}
+83
View File
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
pragma solidity ^0.8.20;
import "fhevm/lib/TFHE.sol";
import "./eip712-reencrypt.sol";
contract EncryptedERC20 is EIP712Reencrypt {
address public contractOwner;
uint64 public totalSupply;
constructor() {
contractOwner = msg.sender;
}
mapping(address => euint64) internal balances;
function balanceOf(
address wallet,
bytes32 publicKey,
bytes calldata signature
)
public
view
signedBySender(publicKey, signature)
returns (bytes memory)
{
require(wallet == msg.sender);
return TFHE.reencrypt(balances[msg.sender], publicKey, 0);
}
function mint(uint64 amount) public {
require(msg.sender == contractOwner);
balances[contractOwner] = TFHE.add(balances[contractOwner], amount);
totalSupply = totalSupply + amount;
}
function transfer(address to, bytes calldata amountCiphertext) public returns (bool) {
return transfer_reverting(to, amountCiphertext);
// return transfer_leaking(to, amountCiphertext);
// return transfer_nonleaking(to, amountCiphertext);
}
function transfer_reverting(address to, bytes calldata amountCiphertext) internal returns (bool) {
euint64 amount = TFHE.asEuint64(amountCiphertext);
ebool sufficient = TFHE.le(amount, balances[msg.sender]);
bool decrypted_sufficient = TFHE.decrypt(sufficient);
require(decrypted_sufficient);
balances[to] = balances[to] + amount;
balances[msg.sender] = balances[msg.sender] - amount;
return true;
}
function transfer_leaking(address to, bytes calldata amountCiphertext) internal returns (bool) {
euint64 amount = TFHE.asEuint64(amountCiphertext);
ebool sufficient = TFHE.le(amount, balances[msg.sender]);
bool decrypted_sufficient = TFHE.decrypt(sufficient);
if (decrypted_sufficient) {
balances[to] = balances[to] + amount;
balances[msg.sender] = balances[msg.sender] - amount;
}
return decrypted_sufficient;
}
function transfer_nonleaking(address to, bytes calldata amountCiphertext) internal returns (bool) {
euint64 amount = TFHE.asEuint64(amountCiphertext);
ebool sufficient = TFHE.le(amount, balances[msg.sender]);
balances[to] = balances[to] + TFHE.select(sufficient, amount, TFHE.asEuint64(0));
balances[msg.sender] = balances[msg.sender] - TFHE.select(sufficient, amount, TFHE.asEuint64(0));
return true;
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"name": "fhevmjs-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"balanceOf": "node src/balanceOf.js",
"mint": "node src/mint.js",
"transfer": "node src/transfer.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"ethers": "^6.6.3",
"fhevmjs": "^0.4.0"
}
}
+39
View File
@@ -0,0 +1,39 @@
const { Wallet, Contract } = require('ethers');
const { WALLET_PRIVATE_KEY, CONTRACT_ADDRESS } = require('./constants');
const { getInstance, provider } = require('./instance.js');
const abi = require('../../abi.json');
const signer = new Wallet(WALLET_PRIVATE_KEY, provider);
const contract = new Contract(CONTRACT_ADDRESS, abi, signer);
const balanceOf = async () => {
const fhevm = await getInstance();
console.log('Generating public key for reencryption');
const clientPublicKey = fhevm.generatePublicKey({
verifyingContract: CONTRACT_ADDRESS,
});
console.log('Signing public key');
const signature = await signer.signTypedData(
clientPublicKey.eip712.domain,
{ Reencrypt: clientPublicKey.eip712.types.Reencrypt },
clientPublicKey.eip712.message
);
console.log('Calling contract');
const userAddress = await signer.getAddress();
const encryptedBalance = await contract.balanceOf(
userAddress,
clientPublicKey.publicKey,
signature
);
console.log('Decrypting result using private key');
const balance = fhevm.decrypt(CONTRACT_ADDRESS, encryptedBalance);
return balance;
};
balanceOf().then((balance) => {
console.log(`Balance: ${balance}`);
});
+5
View File
@@ -0,0 +1,5 @@
module.exports = {
DEVNET_URL: 'https://devnet.luxfhe.io/',
WALLET_PRIVATE_KEY: process.env.WORKSHOP_PRIVATE_KEY,
CONTRACT_ADDRESS: process.env.CONTRACT,
};
+25
View File
@@ -0,0 +1,25 @@
const { createInstance, getPublicKeyCallParams } = require('fhevmjs');
const { ethers, JsonRpcProvider } = require('ethers');
const { DEVNET_URL } = require('./constants');
let _instance;
const provider = new JsonRpcProvider(DEVNET_URL);
const getInstance = async () => {
if (_instance) return _instance;
// 1. Get chain id
const network = await provider.getNetwork();
const chainId = +network.chainId.toString();
// Get blockchain public key
const rawPublicKeyParams = await provider.call(getPublicKeyCallParams());
const publicKeyParams = ethers.AbiCoder.defaultAbiCoder().decode(["bytes"], rawPublicKeyParams);
const publicKey = publicKeyParams[0];
// Create instance
_instance = createInstance({ chainId, publicKey });
return _instance;
};
module.exports = {
getInstance,
provider,
};
+21
View File
@@ -0,0 +1,21 @@
const { Wallet, Contract } = require('ethers');
const { WALLET_PRIVATE_KEY, CONTRACT_ADDRESS } = require('./constants');
const { getInstance, provider } = require('./instance.js');
const abi = require('../../abi.json');
const signer = new Wallet(WALLET_PRIVATE_KEY, provider);
const contract = new Contract(CONTRACT_ADDRESS, abi, signer);
const mint = async (amount) => {
console.log('Sending transaction');
const transaction = await contract.mint(amount);
console.log('Waiting for transaction validation...');
await provider.waitForTransaction(transaction.hash);
};
mint(+process.argv[2] || 1000)
.then(() => {
console.log('Transaction done!');
})
.catch((err) => console.log('Transaction failed :(', err));
+29
View File
@@ -0,0 +1,29 @@
const { Wallet, Contract } = require('ethers');
const { WALLET_PRIVATE_KEY, WALLET_TO_TRANSFER, CONTRACT_ADDRESS } = require('./constants');
const { getInstance, provider } = require('./instance.js');
const abi = require('../../abi.json');
const signer = new Wallet(WALLET_PRIVATE_KEY, provider);
const contract = new Contract(CONTRACT_ADDRESS, abi, signer);
const transfer = async (to_opt, amount) => {
const fhevm = await getInstance();
// Default to own address if nothing specified
const to = to_opt || await signer.getAddress();
console.log(`Encrypting ${amount}`);
const encryptedAmount = fhevm.encrypt64(amount);
console.log('Sending transaction');
const transaction = await contract['transfer(address,bytes)'](to, encryptedAmount);
console.log('Waiting for transaction validation...');
await provider.waitForTransaction(transaction.hash);
};
transfer(process.argv[2], +process.argv[3] || 100)
.then(() => {
console.log('Transaction done!');
})
.catch((err) => console.log('Transaction failed :(', err));
+22
View File
@@ -0,0 +1,22 @@
import argparse
from fhevm import FHEVM
from utils import load_contract, setup_w3, setup_wallet
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--contract")
args = parser.parse_args()
w3 = setup_w3()
my_account = setup_wallet(w3)
fhevm = FHEVM(w3, my_account)
erc20 = load_contract(w3, args.contract)
# call balanceOf
public_key, signature = fhevm.generate_auth_token(erc20.address)
encrypted_balance = erc20.functions.balanceOf(public_key, signature).call(
{"from": my_account.address}
)
balance = fhevm.open(encrypted_balance)
print(f"Balance: {balance}")
+62
View File
@@ -0,0 +1,62 @@
import os
import sha3
from eip712_structs import Bytes, EIP712Struct, make_domain
from nacl.public import PrivateKey, SealedBox
PUBLIC_KEY_CONTRACT = "0x0000000000000000000000000000000000000044"
class Reencrypt(EIP712Struct):
publicKey = Bytes(32)
class FHEVM:
def __init__(self, w3, account):
self.network_encryption_key = None
self.my_decryption_key = PrivateKey.generate()
self.w3 = w3
self.my_account = account
def encrypt32(self, plaintext):
if self.network_encryption_key is None:
print("Fetching global public key")
self.network_encryption_key = self.w3.eth.call({"to": PUBLIC_KEY_CONTRACT})
with open("/tmp/zama_network_public_key", mode="wb") as f:
f.write(self.network_encryption_key)
res = os.system(
f"fhevm-tfhe-cli public-encrypt-integer32 -v {plaintext} -c /tmp/zama_ciphertext -p /tmp/zama_network_public_key"
)
assert res == 0, "fail to execute fhe-tool"
with open("/tmp/zama_ciphertext", mode="rb") as file:
ciphertext = file.read()
assert len(ciphertext) == 8404
return ciphertext
def generate_auth_token(self, contract_address):
domain = make_domain(
name="Authorization token",
version="1",
chainId=self.w3.eth.chain_id,
verifyingContract=contract_address,
)
msg = Reencrypt()
msg["publicKey"] = self.my_decryption_key.public_key._public_key
assert len(self.my_decryption_key.public_key._public_key) == 32
signable_bytes = msg.signable_bytes(domain)
msg_hash = sha3.keccak_256(signable_bytes).digest()
msg_sig = self.my_account.signHash(msg_hash)
sig = bytes.fromhex(msg_sig.signature.hex()[2:])
public_key = self.my_decryption_key.public_key._public_key
return public_key, sig
def open(self, ciphertext):
unseal_box = SealedBox(self.my_decryption_key)
plaintext_bytes = unseal_box.decrypt(ciphertext)
plaintext = int.from_bytes(plaintext_bytes, "big")
return plaintext
+20
View File
@@ -0,0 +1,20 @@
import argparse
from fhevm import FHEVM
from utils import load_contract, send_transaction, setup_w3, setup_wallet
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--contract")
parser.add_argument("-a", "--amount", default=100)
args = parser.parse_args()
w3 = setup_w3()
my_account = setup_wallet(w3)
fhevm = FHEVM(w3, my_account)
erc20 = load_contract(w3, args.contract)
# call mint
amount = fhevm.encrypt32(args.amount)
mint = erc20.functions.mint(amount)
send_transaction(w3, mint, my_account.address)
+50
View File
@@ -0,0 +1,50 @@
aiohttp==3.8.4
aiosignal==1.3.1
async-timeout==4.0.2
attrs==23.1.0
bitarray==2.7.6
black==23.7.0
certifi==2023.5.7
cffi==1.15.1
charset-normalizer==3.2.0
click==8.1.4
cytoolz==0.12.1
eip712-structs==1.1.0
eth-abi==4.1.0
eth-account==0.9.0
eth-hash==0.5.2
eth-keyfile==0.6.1
eth-keys==0.4.0
eth-rlp==0.3.0
eth-typing==3.4.0
eth-utils==2.2.0
frozenlist==1.3.3
hexbytes==0.3.1
idna==3.4
isort==5.12.0
jsonschema==4.18.1
jsonschema-specifications==2023.6.1
lru-dict==1.2.0
multidict==6.0.4
mypy-extensions==1.0.0
packaging==23.1
parsimonious==0.9.0
pathspec==0.11.1
platformdirs==3.8.1
protobuf==4.23.4
pycparser==2.21
pycryptodome==3.18.0
PyNaCl==1.5.0
pysha3==1.0.2
referencing==0.29.1
regex==2023.6.3
requests==2.31.0
rlp==3.0.0
rpds-py==0.8.10
tomli==2.0.1
toolz==0.12.0
typing_extensions==4.7.1
urllib3==2.0.3
web3==6.5.0
websockets==11.0.3
yarl==1.9.2
+22
View File
@@ -0,0 +1,22 @@
import argparse
from fhevm import FHEVM
from utils import load_contract, send_transaction, setup_w3, setup_wallet
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("-c", "--contract")
parser.add_argument("-t", "--to", default=None)
parser.add_argument("-a", "--amount", default=10)
args = parser.parse_args()
w3 = setup_w3()
my_account = setup_wallet(w3)
fhevm = FHEVM(w3, my_account)
erc20 = load_contract(w3, args.contract)
# call transfer
amount = fhevm.encrypt32(args.amount)
to = args.to or my_account.address
transfer = erc20.functions.transfer(to, amount)
send_transaction(w3, transfer, my_account.address)
+53
View File
@@ -0,0 +1,53 @@
import json
import os
from eth_account import Account
from web3 import Web3
from web3.middleware import construct_sign_and_send_raw_middleware
SIGNATURE_KEY_VAR = "WORKSHOP_PRIVATE_KEY"
DEVNET_VAR = "ETHCC23_DEVNET"
DEFAULT_DEVNET = "https://devnet.zama.ai"
def setup_w3():
devnet = os.environ.get(DEVNET_VAR, DEFAULT_DEVNET)
return Web3(Web3.HTTPProvider(devnet, request_kwargs={"timeout": 600}))
def setup_wallet(w3):
signature_key = os.environ.get(SIGNATURE_KEY_VAR)
assert signature_key != None, f"Please specify env variable '{SIGNATURE_KEY_VAR}'"
if not signature_key.startswith("0x"):
signature_key = "0x" + signature_key
account = Account.from_key(signature_key)
w3.middleware_onion.add(construct_sign_and_send_raw_middleware(account))
w3.eth.default_account = account.address
print(f"Account address: {account.address}")
return account
def send_transaction(w3, tx, from_address):
# # estimate gas
# gas = tx.estimate_gas({"value": 0, "from": from_address})
# print(f"Gas estimation: {gas}")
# send transaction
tx_hash = tx.transact({"value": 0, "from": from_address}).hex()
print(f"Transaction hash: {tx_hash}")
# wait for transaction to go through
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
assert tx_receipt["status"] == 1
def load_contract(w3, address):
print(f"Contract address: {address}")
with open("../abi.json", "rt") as f:
abi = json.load(f)
return w3.eth.contract(
address=address,
abi=abi,
)
+1556
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
{
"name": "@luxfhe/e2e",
"version": "1.0.0",
"private": true,
"description": "LuxFHE End-to-End Tests",
"type": "module",
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:server": "./scripts/start-server.sh & sleep 2 && npm test; kill %1",
"start:server": "cd ~/work/lux/tfhe && ./bin/fhe-server -addr :8448"
},
"devDependencies": {
"vitest": "^3.2.3",
"typescript": "^5.9.0"
}
}
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
# Start FHE server for e2e tests
set -e
TFHE_DIR="$HOME/work/lux/tfhe"
FHE_SERVER="$TFHE_DIR/bin/fhe-server"
# Build if needed
if [ ! -f "$FHE_SERVER" ]; then
echo "Building FHE server..."
cd "$TFHE_DIR"
go build -o bin/fhe-server ./cmd/fhe-server/
fi
echo "Starting FHE server on :8448..."
exec "$FHE_SERVER" -addr :8448
+191
View File
@@ -0,0 +1,191 @@
/**
* LuxFHE End-to-End Tests
*
* Tests the full FHE stack:
* 1. Go TFHE server (http://localhost:8448)
* 2. WASM bindings (@luxfhe/wasm-node)
* 3. KMS client (@luxfhe/kms-node)
*
* Prerequisites:
* cd ~/work/lux/tfhe && ./bin/fhe-server -addr :8448
*/
import { describe, it, expect, beforeAll } from 'vitest';
const FHE_SERVER_URL = process.env.FHE_SERVER_URL || 'http://localhost:8448';
describe('LuxFHE E2E Tests', () => {
beforeAll(async () => {
// Check if server is running
try {
const res = await fetch(`${FHE_SERVER_URL}/health`);
if (!res.ok) throw new Error('Server not healthy');
} catch (e) {
console.error('FHE server not running. Start with:');
console.error(' cd ~/work/lux/tfhe && ./bin/fhe-server');
throw e;
}
});
describe('Health Check', () => {
it('should return healthy status', async () => {
const res = await fetch(`${FHE_SERVER_URL}/health`);
expect(res.ok).toBe(true);
const data = await res.json();
expect(data.status).toBe('ok');
});
});
describe('Public Key', () => {
it('should return a valid public key', async () => {
const res = await fetch(`${FHE_SERVER_URL}/publickey`);
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` Public key size: ${buffer.byteLength} bytes`);
});
});
describe('Encryption', () => {
it('should encrypt a 32-bit integer', async () => {
const value = 42;
const res = await fetch(`${FHE_SERVER_URL}/encrypt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ value, bitWidth: 32 }),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` Encrypted ${value} -> ${buffer.byteLength} bytes`);
});
it('should encrypt different bit widths', async () => {
const bitWidths = [8, 16, 32, 64];
for (const bitWidth of bitWidths) {
const value = 123;
const res = await fetch(`${FHE_SERVER_URL}/encrypt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ value, bitWidth }),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
console.log(` FheUint${bitWidth}: ${buffer.byteLength} bytes`);
}
});
});
describe('FHE Operations', () => {
let encA: Uint8Array;
let encB: Uint8Array;
beforeAll(async () => {
// Encrypt two values
const resA = await fetch(`${FHE_SERVER_URL}/encrypt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ value: 42, bitWidth: 32 }),
});
encA = new Uint8Array(await resA.arrayBuffer());
const resB = await fetch(`${FHE_SERVER_URL}/encrypt`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ value: 17, bitWidth: 32 }),
});
encB = new Uint8Array(await resB.arrayBuffer());
});
it('should add two encrypted values', async () => {
const res = await fetch(`${FHE_SERVER_URL}/evaluate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
op: 'add',
left: Array.from(encA),
right: Array.from(encB),
bitWidth: 32,
}),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` add(42, 17) = encrypted (${buffer.byteLength} bytes)`);
});
it('should subtract two encrypted values', async () => {
const res = await fetch(`${FHE_SERVER_URL}/evaluate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
op: 'sub',
left: Array.from(encA),
right: Array.from(encB),
bitWidth: 32,
}),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` sub(42, 17) = encrypted (${buffer.byteLength} bytes)`);
});
it('should compare two encrypted values (lt)', async () => {
const res = await fetch(`${FHE_SERVER_URL}/evaluate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
op: 'lt',
left: Array.from(encA),
right: Array.from(encB),
bitWidth: 32,
}),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` lt(42, 17) = encrypted bool (${buffer.byteLength} bytes)`);
});
it('should compare two encrypted values (eq)', async () => {
const res = await fetch(`${FHE_SERVER_URL}/evaluate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
op: 'eq',
left: Array.from(encA),
right: Array.from(encA), // Same value
bitWidth: 32,
}),
});
expect(res.ok).toBe(true);
const buffer = await res.arrayBuffer();
expect(buffer.byteLength).toBeGreaterThan(0);
console.log(` eq(42, 42) = encrypted bool (${buffer.byteLength} bytes)`);
});
});
describe('ZK Verification', () => {
it('should verify a computation proof', async () => {
const res = await fetch(`${FHE_SERVER_URL}/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream' },
body: new Uint8Array([1, 2, 3]), // Placeholder proof
});
expect(res.ok).toBe(true);
const data = await res.json();
expect(data.verified).toBe(true);
});
});
});
+9
View File
@@ -0,0 +1,9 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['test/**/*.test.ts'],
testTimeout: 30000,
hookTimeout: 30000,
},
});
-96
View File
@@ -1,96 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
package fhe
import (
"github.com/luxfi/lattice/v7/core/rlwe"
)
// Encryptor encrypts boolean values into FHE ciphertexts
type Encryptor struct {
params Parameters
encryptor *rlwe.Encryptor
scale float64
}
// NewEncryptor creates a new encryptor from secret key
func NewEncryptor(params Parameters, sk *SecretKey) *Encryptor {
return &Encryptor{
params: params,
encryptor: rlwe.NewEncryptor(params.paramsLWE, sk.SKLWE),
scale: float64(params.QLWE()) / 4.0, // Encode bit as Q/4 or -Q/4
}
}
// Encrypt encrypts a boolean value
// Note: Panics on error (should not happen with valid parameters)
func (enc *Encryptor) Encrypt(value bool) *Ciphertext {
pt := rlwe.NewPlaintext(enc.params.paramsLWE, enc.params.paramsLWE.MaxLevel())
q := enc.params.QLWE()
// Encode with Q/8 scale so sums of two bits stay in distinguishable range:
// - true -> +Q/8 (normalized +0.5 relative to Q/4 scale)
// - false -> -Q/8 (normalized -0.5)
// After sum:
// - (0,0): -Q/4 normalized to -1
// - (0,1): 0 normalized to 0
// - (1,1): +Q/4 normalized to +1
if value {
pt.Value.Coeffs[0][0] = q / 8
} else {
pt.Value.Coeffs[0][0] = q - (q / 8) // = -Q/8 mod Q
}
enc.params.paramsLWE.RingQ().NTT(pt.Value, pt.Value)
ct := rlwe.NewCiphertext(enc.params.paramsLWE, 1, enc.params.paramsLWE.MaxLevel())
if err := enc.encryptor.Encrypt(pt, ct); err != nil {
panic(err) // Should not happen with valid parameters
}
return &Ciphertext{ct}
}
// EncryptBit is an alias for Encrypt
func (enc *Encryptor) EncryptBit(bit int) *Ciphertext {
return enc.Encrypt(bit != 0)
}
// EncryptByte encrypts a byte as 8 ciphertexts (LSB first)
func (enc *Encryptor) EncryptByte(b byte) [8]*Ciphertext {
var cts [8]*Ciphertext
for i := 0; i < 8; i++ {
cts[i] = enc.Encrypt((b>>i)&1 == 1)
}
return cts
}
// EncryptUint32 encrypts a uint32 as 32 ciphertexts (LSB first)
func (enc *Encryptor) EncryptUint32(v uint32) [32]*Ciphertext {
var cts [32]*Ciphertext
for i := 0; i < 32; i++ {
cts[i] = enc.Encrypt((v>>i)&1 == 1)
}
return cts
}
// EncryptUint64 encrypts a uint64 as 64 ciphertexts (LSB first)
func (enc *Encryptor) EncryptUint64(v uint64) [64]*Ciphertext {
var cts [64]*Ciphertext
for i := 0; i < 64; i++ {
cts[i] = enc.Encrypt((v>>i)&1 == 1)
}
return cts
}
// EncryptUint256 encrypts a 256-bit value as 256 ciphertexts (LSB first)
func (enc *Encryptor) EncryptUint256(v [4]uint64) [256]*Ciphertext {
var cts [256]*Ciphertext
for w := 0; w < 4; w++ {
for i := 0; i < 64; i++ {
cts[w*64+i] = enc.Encrypt((v[w]>>i)&1 == 1)
}
}
return cts
}
-341
View File
@@ -1,341 +0,0 @@
// Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause
package fhe
import (
"fmt"
"github.com/luxfi/lattice/v7/core/rgsw/blindrot"
"github.com/luxfi/lattice/v7/core/rlwe"
"github.com/luxfi/lattice/v7/ring"
)
// Evaluator evaluates boolean gates on encrypted data
// SECURITY: This evaluator does NOT require the secret key.
// It uses sample extraction and key switching for bootstrapping.
type Evaluator struct {
params Parameters
eval *blindrot.Evaluator
bsk *BootstrapKey
ringQLWE *ring.Ring
ringQBR *ring.Ring
// Key switching evaluator (BR -> LWE)
ksEval *rlwe.Evaluator
}
// NewEvaluator creates a new evaluator with bootstrap key.
// SECURITY: No secret key is required - bootstrapping uses public key switching.
func NewEvaluator(params Parameters, bsk *BootstrapKey) *Evaluator {
// Create key switching evaluator using the key switch key in bootstrap key
var ksEval *rlwe.Evaluator
if bsk.KSK != nil {
ksEval = rlwe.NewEvaluator(params.paramsBR, nil)
}
return &Evaluator{
params: params,
eval: blindrot.NewEvaluator(params.paramsBR, params.paramsLWE),
bsk: bsk,
ringQLWE: params.paramsLWE.RingQ(),
ringQBR: params.paramsBR.RingQ(),
ksEval: ksEval,
}
}
// sampleExtractAndModSwitch extracts the result from an RLWE ciphertext
// after blind rotation and converts it to an LWE ciphertext.
//
// When LWE and BR use the same dimension and modulus (recommended configuration),
// this simply returns the ciphertext directly since no conversion is needed.
//
// SECURITY: This operation does NOT require the secret key. The ciphertext
// remains encrypted throughout.
func (eval *Evaluator) sampleExtractAndModSwitch(ctBR *rlwe.Ciphertext) (*Ciphertext, error) {
// When same dimension and modulus, just return the ciphertext directly
// The key is the same, so no conversion needed
if eval.params.N() == eval.params.NBR() && eval.params.QLWE() == eval.params.QBR() {
// Copy to a new ciphertext in LWE parameters (same as BR here)
result := ctBR.CopyNew()
return &Ciphertext{result}, nil
}
// Different dimensions/moduli require modulus switching
levelBR := ctBR.Level()
ringQBR := eval.ringQBR.AtLevel(levelBR)
qBR := eval.params.QBR()
qLWE := eval.params.QLWE()
// Ensure we're working in coefficient domain
c0 := ctBR.Value[0].CopyNew()
c1 := ctBR.Value[1].CopyNew()
if ctBR.IsNTT {
ringQBR.INTT(*c0, *c0)
ringQBR.INTT(*c1, *c1)
}
// Create output ciphertext in LWE parameters
nLWE := eval.params.N()
ctLWE := rlwe.NewCiphertext(eval.params.paramsLWE, 1, eval.params.paramsLWE.MaxLevel())
scaleFactor := float64(qLWE) / float64(qBR)
// Scale and copy first N_LWE coefficients
for i := 0; i < nLWE; i++ {
scaled0 := uint64(float64(c0.Coeffs[0][i])*scaleFactor + 0.5)
scaled1 := uint64(float64(c1.Coeffs[0][i])*scaleFactor + 0.5)
ctLWE.Value[0].Coeffs[0][i] = scaled0 % qLWE
ctLWE.Value[1].Coeffs[0][i] = scaled1 % qLWE
}
// Convert to NTT
ringQLWE := eval.ringQLWE.AtLevel(eval.params.paramsLWE.MaxLevel())
ringQLWE.NTT(ctLWE.Value[0], ctLWE.Value[0])
ringQLWE.NTT(ctLWE.Value[1], ctLWE.Value[1])
ctLWE.IsNTT = true
return &Ciphertext{ctLWE}, nil
}
// bootstrap performs programmable bootstrapping with the given test polynomial
// and returns a fresh LWE ciphertext with the result.
//
// SECURITY: This implementation does NOT decrypt - it uses sample extraction
// and key switching, which are public operations on ciphertexts.
func (eval *Evaluator) bootstrap(ct *Ciphertext, testPoly *ring.Poly) (*Ciphertext, error) {
// Create map for single slot evaluation
testPolyMap := map[int]*ring.Poly{0: testPoly}
// Step 1: Evaluate blind rotation
// This produces an RLWE ciphertext under SKBR with the test polynomial
// evaluated at the encrypted value
results, err := eval.eval.Evaluate(ct.Ciphertext, testPolyMap, eval.bsk.BRK)
if err != nil {
return nil, fmt.Errorf("bootstrap: %w", err)
}
// Extract result for slot 0
ctBR, ok := results[0]
if !ok {
return nil, fmt.Errorf("bootstrap: no result for slot 0")
}
// Step 2: Sample extract and modulus switch
// This extracts the result and scales to the LWE modulus
return eval.sampleExtractAndModSwitch(ctBR)
}
// addCiphertexts adds two ciphertexts element-wise
func (eval *Evaluator) addCiphertexts(ct1, ct2 *Ciphertext) *Ciphertext {
result := rlwe.NewCiphertext(eval.params.paramsLWE, 1, ct1.Level())
eval.ringQLWE.Add(ct1.Value[0], ct2.Value[0], result.Value[0])
eval.ringQLWE.Add(ct1.Value[1], ct2.Value[1], result.Value[1])
result.IsNTT = ct1.IsNTT
return &Ciphertext{result}
}
// doubleCiphertext multiplies a ciphertext by 2 (element-wise addition with itself)
// This is key to OpenFHE's optimized XOR: 2*(ct1+ct2) causes wrap-around for (T,T) case
func (eval *Evaluator) doubleCiphertext(ct *Ciphertext) *Ciphertext {
result := rlwe.NewCiphertext(eval.params.paramsLWE, 1, ct.Level())
eval.ringQLWE.Add(ct.Value[0], ct.Value[0], result.Value[0])
eval.ringQLWE.Add(ct.Value[1], ct.Value[1], result.Value[1])
result.IsNTT = ct.IsNTT
return &Ciphertext{result}
}
// negateCiphertext negates a ciphertext
func (eval *Evaluator) negateCiphertext(ct *Ciphertext) *Ciphertext {
result := rlwe.NewCiphertext(eval.params.paramsLWE, 1, ct.Level())
eval.ringQLWE.Neg(ct.Value[0], result.Value[0])
eval.ringQLWE.Neg(ct.Value[1], result.Value[1])
result.IsNTT = ct.IsNTT
return &Ciphertext{result}
}
// addConstant adds a scalar constant to the ciphertext's constant term (b)
// This is used for gate offsets like OpenFHE's gate constants
func (eval *Evaluator) addConstant(ct *Ciphertext, constant uint64) *Ciphertext {
result := ct.CopyNew()
// Add constant to the constant term (coefficient 0 of polynomial b)
// Need to handle NTT form
if result.IsNTT {
eval.ringQLWE.INTT(result.Value[1], result.Value[1])
}
q := eval.params.QLWE()
result.Value[1].Coeffs[0][0] = (result.Value[1].Coeffs[0][0] + constant) % q
if ct.IsNTT {
eval.ringQLWE.NTT(result.Value[1], result.Value[1])
}
return &Ciphertext{result}
}
// ========== Boolean Gates ==========
// NOT computes the logical NOT of the input
// NOT(a) = 1 - a (free operation - just negate)
func (eval *Evaluator) NOT(ct *Ciphertext) *Ciphertext {
return eval.negateCiphertext(ct)
}
// AND computes the logical AND of two inputs
// AND(a, b) = 1 if a + b >= 1.5 (both are 1)
func (eval *Evaluator) AND(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
return eval.bootstrap(sum, eval.bsk.TestPolyAND)
}
// OR computes the logical OR of two inputs
// OR(a, b) = 1 if a + b >= 0.5 (at least one is 1)
func (eval *Evaluator) OR(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
return eval.bootstrap(sum, eval.bsk.TestPolyOR)
}
// XOR computes the logical XOR of two inputs
// Optimized algorithm matching OpenFHE: 2*(ct1 + ct2) with single bootstrap
// The doubling causes (T,T) → 2*0.25 = 0.5 to wrap around to -0.5,
// making the XOR test polynomial correctly return FALSE for both (T,T) and (F,F)
func (eval *Evaluator) XOR(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
doubled := eval.doubleCiphertext(sum) // Key: 2*(ct1+ct2)
return eval.bootstrap(doubled, eval.bsk.TestPolyXOR)
}
// NAND computes the logical NAND of two inputs
func (eval *Evaluator) NAND(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
return eval.bootstrap(sum, eval.bsk.TestPolyNAND)
}
// NOR computes the logical NOR of two inputs
func (eval *Evaluator) NOR(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
return eval.bootstrap(sum, eval.bsk.TestPolyNOR)
}
// XNOR computes the logical XNOR of two inputs
// Optimized algorithm matching OpenFHE: 2*(ct1 + ct2) with single bootstrap
// Same as XOR but with inverted test polynomial
func (eval *Evaluator) XNOR(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
doubled := eval.doubleCiphertext(sum) // Key: 2*(ct1+ct2)
return eval.bootstrap(doubled, eval.bsk.TestPolyXNOR)
}
// ANDNY computes AND with negated first input: AND(NOT(a), b)
func (eval *Evaluator) ANDNY(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
return eval.AND(eval.NOT(ct1), ct2)
}
// ANDYN computes AND with negated second input: AND(a, NOT(b))
func (eval *Evaluator) ANDYN(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
return eval.AND(ct1, eval.NOT(ct2))
}
// ORNY computes OR with negated first input: OR(NOT(a), b)
func (eval *Evaluator) ORNY(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
return eval.OR(eval.NOT(ct1), ct2)
}
// ORYN computes OR with negated second input: OR(a, NOT(b))
func (eval *Evaluator) ORYN(ct1, ct2 *Ciphertext) (*Ciphertext, error) {
return eval.OR(ct1, eval.NOT(ct2))
}
// MUX computes the multiplexer: if sel then a else b
// MUX(sel, a, b) = (sel AND a) OR (NOT(sel) AND b)
func (eval *Evaluator) MUX(sel, ctTrue, ctFalse *Ciphertext) (*Ciphertext, error) {
selAndTrue, err := eval.AND(sel, ctTrue)
if err != nil {
return nil, err
}
notSelAndFalse, err := eval.AND(eval.NOT(sel), ctFalse)
if err != nil {
return nil, err
}
return eval.OR(selAndTrue, notSelAndFalse)
}
// ========== Multi-Input Gates ==========
//
// Note: Single-bootstrap multi-input gates require careful offset tuning
// matching OpenFHE's gate constants. For correctness, we use 2-bootstrap
// composition here. Future optimization could add single-bootstrap versions.
// AND3 computes the logical AND of three inputs
// AND3(a, b, c) = AND(AND(a, b), c)
func (eval *Evaluator) AND3(ct1, ct2, ct3 *Ciphertext) (*Ciphertext, error) {
ab, err := eval.AND(ct1, ct2)
if err != nil {
return nil, err
}
return eval.AND(ab, ct3)
}
// OR3 computes the logical OR of three inputs
// OR3(a, b, c) = OR(OR(a, b), c)
func (eval *Evaluator) OR3(ct1, ct2, ct3 *Ciphertext) (*Ciphertext, error) {
ab, err := eval.OR(ct1, ct2)
if err != nil {
return nil, err
}
return eval.OR(ab, ct3)
}
// MAJORITY computes the majority vote of three inputs with single bootstrap
// MAJORITY(a, b, c) = 1 if at least two inputs are 1
// This uses a single bootstrap since the threshold at 0 correctly separates
// 0-1 true inputs (sum < 0) from 2-3 true inputs (sum > 0)
func (eval *Evaluator) MAJORITY(ct1, ct2, ct3 *Ciphertext) (*Ciphertext, error) {
sum := eval.addCiphertexts(ct1, ct2)
sum = eval.addCiphertexts(sum, ct3)
return eval.bootstrap(sum, eval.bsk.TestPolyMAJORITY)
}
// NAND3 computes the logical NAND of three inputs
// NAND3(a, b, c) = NOT(AND3(a, b, c))
func (eval *Evaluator) NAND3(ct1, ct2, ct3 *Ciphertext) (*Ciphertext, error) {
result, err := eval.AND3(ct1, ct2, ct3)
if err != nil {
return nil, err
}
return eval.NOT(result), nil
}
// NOR3 computes the logical NOR of three inputs
// NOR3(a, b, c) = NOT(OR3(a, b, c))
func (eval *Evaluator) NOR3(ct1, ct2, ct3 *Ciphertext) (*Ciphertext, error) {
result, err := eval.OR3(ct1, ct2, ct3)
if err != nil {
return nil, err
}
return eval.NOT(result), nil
}
// Copy creates a copy of a ciphertext
func (eval *Evaluator) Copy(ct *Ciphertext) *Ciphertext {
return &Ciphertext{ct.CopyNew()}
}
// Refresh bootstraps a ciphertext to reduce noise
func (eval *Evaluator) Refresh(ct *Ciphertext) (*Ciphertext, error) {
return eval.bootstrap(ct, eval.bsk.TestPolyID)
}

Some files were not shown because too many files have changed in this diff Show More