Blindference Node – Confidential inference worker for agentic AI.
Project description
Blindference Node
Confidential inference worker for the Blindference decentralized AI execution network.
Run encrypted inference jobs, earn fees, and help build a private, verifiable, and economically accountable AI execution layer on Arbitrum Sepolia.
What It Does
Blindference Node is the runtime that executes confidential inference tasks assigned by the Inference Coordination Layer (ICL). Each node:
- Attests its identity and capabilities to the ICL (mock TEE for tier 0, TPM/TEE for higher tiers)
- Heartbeats every 60 seconds to prove liveness (ICL) and every 10 days on-chain
- Polls for pending job assignments every 5 seconds
- Decrypts encrypted prompts via CoFHE threshold FHE under strict ACL
- Executes inference via Groq Llama 3, Google Gemini, or local vLLM (pluggable backends)
- Commits results back to the ICL for quorum consensus
- Earns fees for successful task completion
Quick Start
1. Install
pip install blindference-node
For GPU-accelerated local inference (optional):
pip install "blindference-node[gpu]"
Or install from source:
git clone https://github.com/AbhishekPanwarr/Blindference-node.git
cd Blindference-node
pip install -e .
2. Initialize
blindference-node init
This will:
- Detect GPU capabilities (or default to mock inference)
- Auto-detect cloud API keys (Groq / Gemini) from environment
- Generate an encrypted Ethereum wallet keystore
- Save configuration to
~/.blindference/config.json
Non-interactive mode:
export BLF_PRIVATE_KEY=0x...
export BLF_KEY_PASSWORD=secure_password
blindference-node init
3. Attest
# Interactive attestation (choose mock or TEE)
blindference-node attest
# Or skip interactive menu and use mock directly
blindference-node attest --mock
# With custom development key
blindference-node attest --mock --tee-key mydevkey
After ICL attestation, optionally register on-chain with gas estimation.
4. Stake BLIND Tokens
Nodes must stake at least 1000 BLIND to participate in inference quorums. Staking provides economic security — stake is slashed if a node produces incorrect output or times out.
# Stake 1000 BLIND (minimum)
blindference-node staking stake 1000
# Check your stake status
blindference-node staking status
# Initiate unstake (starts 96h unbonding)
blindference-node staking unstake
# Complete unstake after unbonding period
blindference-node staking withdraw
Staking Economics:
- Minimum stake: 1000 BLIND
- Unbonding period: 96 hours
- Reward per job: 1 BLIND (60% leader, 20% each verifier)
- Slashing: 3 consecutive failures → entire stake hard-slashed on-chain
5. Run
blindference-node run
The daemon starts four concurrent loops:
| Loop | Frequency | Purpose |
|---|---|---|
| ICL Heartbeat | Every 60s | Proves liveness to ICL (free REST call) |
| On-Chain Heartbeat | Every 10 days | Proves liveness to NodeRegistry (gas tx) |
| Attestation Watchdog | Every 10min | Auto-re-attests if certificate expires within 6h |
| Assignment Poller | Every 5s | Polls ICL for pending inference jobs |
Commands
| Command | Description | Status |
|---|---|---|
init |
Initialize node — wallet, GPU detection, save config | ✅ Ready |
attest |
Attest node with ICL (mock / TEE) and optionally register on-chain | ✅ Ready |
run |
Start daemon — heartbeat, watchdog, job polling & execution | ✅ Ready |
status |
Show node status — address, tier, models, cert expiry | ✅ Ready |
staking stake |
Stake BLIND tokens to join inference quorums | ✅ Ready |
staking unstake |
Initiate unstake (starts 96h unbonding) | ✅ Ready |
staking withdraw |
Complete withdrawal after unbonding period | ✅ Ready |
staking status |
Show BLIND stake status and failure count | ✅ Ready |
models list |
List all registered inference backends and availability | ✅ Ready |
models test |
Test a specific backend with a prompt | ✅ Ready |
models add |
Register a custom backend from a dotted Python path | ✅ Ready |
test-determinism |
Run GPU determinism self-test with vLLM or cloud APIs | ✅ Ready |
jobs list |
List completed jobs and BLIND earnings | ✅ Ready |
jobs earnings |
Total BLIND earned across all completed jobs | ✅ Ready |
balance |
Current BLIND token balance | ✅ Ready |
Architecture
flowchart TB
subgraph "Blindference Node"
DAEMON[Daemon Process]
HB[ICL Heartbeat<br/>60s]
ONCHAIN[On-Chain Heartbeat<br/>10 days]
WD[Attestation Watchdog<br/>10min]
POLL[Assignment Poller<br/>5s]
WORKER[Job Worker]
DAEMON --> HB
DAEMON --> ONCHAIN
DAEMON --> WD
DAEMON --> POLL
POLL -->|dispatch| WORKER
end
subgraph "External Services"
ICL[ICL Coordinator]
COFHE[CoFHE Network]
IPFS[IPFS Gateway]
LLM[Groq / Gemini / vLLM]
CHAIN[Arbitrum Sepolia]
end
HB -->|POST /internal/heartbeat| ICL
ONCHAIN -->|NodeRegistry.heartbeat()| CHAIN
WD -->|GET /internal/challenge| ICL
WD -->|POST /internal/attestation/verify| ICL
POLL -->|GET /internal/assignments/{addr}| ICL
WORKER -->|POST /internal/task/claim| ICL
WORKER -->|decryptForView| COFHE
WORKER -->|download blob| IPFS
WORKER -->|run inference| LLM
WORKER -->|POST /internal/task/result| ICL
ICL -->|register attestation| CHAIN
Configuration
All configuration is stored in ~/.blindference/config.json and can be overridden via environment variables prefixed with BLF_.
Default Config
{
"node_address": "0x...",
"keystore_path": "~/.blindference/keystore.json",
"tier": 0,
"supported_model_ids": ["facebook/opt-125m"],
"custom_backends": [],
"attestation_backend": "mock",
"icl_endpoint": "https://icl.blindference.xyz",
"fhenix_rpc": "https://testnet.fhenix.zone",
"ipfs_gateway": "https://node.lighthouse.storage",
"model_cache_dir": "~/.blindference/models",
"log_level": "INFO",
"network": "fhenix_testnet",
"attestation_cert_hash": "",
"attestation_expiry": 0,
"registered_on_chain": false,
"stake_amount_wei": 0,
"cofhe_mode": "bridge",
"cofhe_endpoint": "",
"cofhe_chain_id": 421614,
"skip_output_key_storage": false
}
Environment Variables
| Variable | Type | Description |
|---|---|---|
BLF_NODE_ADDRESS |
string | Ethereum address (0x...) |
BLF_KEYSTORE_PATH |
string | Path to encrypted keystore |
BLF_TIER |
int | Attestation tier (0=mock, 1=TPM, 2=TEE) |
BLF_SUPPORTED_MODEL_IDS |
list | Comma-separated model IDs |
BLF_CUSTOM_BACKENDS |
list | Dotted Python paths for custom backends |
BLF_ATTESTATION_BACKEND |
string | mock, tpm, or sgx |
BLF_ICL_ENDPOINT |
string | ICL base URL |
BLF_FHENIX_RPC |
string | EVM RPC endpoint |
BLF_IPFS_GATEWAY |
string | IPFS download/upload gateway |
BLF_LOG_LEVEL |
string | DEBUG, INFO, WARNING, ERROR |
BLF_COFHE_MODE |
string | bridge (TypeScript subprocess) or python (HTTP) |
BLF_COFHE_ENDPOINT |
string | CoFHE/EVM RPC endpoint |
BLF_COFHE_CHAIN_ID |
int | Chain ID for CoFHE (421614 for Arbitrum Sepolia) |
BLF_KEY_PASSWORD |
string | Keystore decryption password |
GROQ_API_KEY |
string | Enables Groq cloud backend |
GOOGLE_API_KEY |
string | Enables Gemini cloud backend |
MOCK_ATTESTATION_KEY |
string | Override default mock attestation key |
CoFHE Modes
bridge (default): Spawns a TypeScript subprocess via @cofhe/sdk/node for CoFHE operations. More reliable, handles SDK lifecycle correctly.
python (alternative): Direct HTTP calls to CoFHE endpoints. Lighter weight but requires manual session management.
Model Backends
Blindference Node uses a pluggable backend registry to support multiple inference providers.
Built-in Backends
| Backend | Description | Requirements | Model IDs |
|---|---|---|---|
vllm |
Local GPU inference | NVIDIA GPU + vllm package |
facebook/opt-125m |
groq |
Groq cloud API | GROQ_API_KEY env var |
groq:llama-3.3-70b-versatile |
gemini |
Google Gemini REST API | GOOGLE_API_KEY env var |
gemini:gemini-2.5-flash |
mock |
Deterministic SHA-256 fallback | Always available | * (universal fallback) |
Custom Backends
from blindference_node.models.base import ModelBackend
class MyBackend(ModelBackend):
def name(self) -> str: return "my-backend"
def is_available(self) -> bool: return True
def supported_models(self) -> list[str]: return ["my-model"]
def run(self, model_id: str, prompt: str) -> str: return "result"
Register via CLI:
blindference-node models add my_package.backends:MyBackend
Node Lifecycle
1. Initialization (init)
sequenceDiagram
participant User
participant Node as blindference-node
User->>Node: init
Node->>Node: detect GPU / cloud API keys
Node->>Node: generate wallet + keystore
Node->>Node: save config
2. Attestation (attest)
sequenceDiagram
participant Node as blindference-node
participant ICL
participant Chain as Arbitrum Sepolia
Node->>ICL: GET /internal/challenge/{addr}
ICL-->>Node: challengeId + nonce
Node->>Node: generate attestation quote
Node->>ICL: POST /internal/attestation/verify
ICL-->>Node: certHash + expiry + tier
opt On-chain registration
Node->>Chain: NodeRegistry.register()
Chain-->>Node: tx hash
end
Node->>Node: save config
3. Daemon Execution (run)
sequenceDiagram
participant Node as blindference-node
participant ICL
participant Chain as Arbitrum Sepolia
participant COFHE as CoFHE Network
participant LLM as Groq/Gemini
Node->>Node: check attestation expiry
alt expired or missing
Node->>ICL: auto-re-attest
end
par ICL Heartbeat
loop Every 60s
Node->>ICL: POST /internal/heartbeat
end
and On-Chain Heartbeat
loop Every 10 days
Node->>Chain: NodeRegistry.heartbeat()
end
and Watchdog
loop Every 10min
Node->>Node: check cert expiry < 6h
alt needs re-attest
Node->>ICL: re-attest
end
end
and Assignment Poller
loop Every 5s
Node->>ICL: GET /internal/assignments/{addr}
alt assignments found
Node->>Node: spawn job worker (max 2 concurrent)
end
end
end
4. Job Execution
sequenceDiagram
participant Worker as Job Worker
participant ICL
participant COFHE as CoFHE Network
participant IPFS
participant LLM as Groq/Gemini
Worker->>ICL: POST /internal/task/claim
ICL-->>Worker: kpHighHandle + kpLowHandle + claimDeadline
alt leader role
Worker->>COFHE: decryptForView(kpHighHandle).withPermit()
Worker->>COFHE: decryptForView(kpLowHandle).withPermit()
Worker->>Worker: reconstruct AES key
Worker->>IPFS: download encrypted prompt blob
Worker->>Worker: AES decrypt prompt
Worker->>LLM: run inference
Worker->>Worker: AES encrypt output
Worker->>Worker: split output key into halves
Worker->>COFHE: encrypt output key halves
Worker->>Chain: storeKey(output key) in PromptKeyStore
Worker->>IPFS: upload encrypted output blob
Worker->>ICL: POST /internal/task/result
else verifier role
Worker->>COFHE: decryptForView(kpHighHandle).withPermit()
Worker->>COFHE: decryptForView(kpLowHandle).withPermit()
Worker->>Worker: reconstruct AES key
Worker->>IPFS: download encrypted prompt blob
Worker->>Worker: AES decrypt prompt
Worker->>LLM: run inference
Worker->>Worker: hash result
Worker->>ICL: POST /internal/task/verify
end
Requirements
- Python: 3.10 or higher
- Operating System: Linux (tested on Ubuntu 22.04), macOS
- GPU (optional): NVIDIA GPU with CUDA support for local vLLM inference
- Network: Outbound HTTPS to ICL, Fhenix RPC, IPFS gateway, Groq/Gemini APIs
- Storage: ~2GB for model cache (if running local models)
Development
Setup
# Clone repository
git clone https://github.com/AbhishekPanwarr/Blindference-node.git
cd Blindference-node
# Create virtual environment
python -m venv venv
source venv/bin/activate
# Install dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
Project Structure
Blindference-node/
├── blindference_node/ # Main package
│ ├── __init__.py
│ ├── cli.py # CLI entry points (init, attest, run, status, models)
│ ├── node_loop.py # Daemon with heartbeat, watchdog, poller
│ ├── job_handler.py # Task execution logic
│ ├── crypto.py # CoFHE client, AES blob encryption/decryption
│ ├── icl_client.py # ICL REST API client
│ ├── wallet.py # Ethereum wallet generation and loading
│ ├── registry.py # On-chain registration and heartbeat
│ ├── config.py # Configuration management
│ ├── attestation/ # Attestation backends (mock, TPM, TEE)
│ ├── models/ # Pluggable inference backends
│ │ ├── base.py
│ │ ├── vllm_backend.py
│ │ ├── groq_backend.py
│ │ ├── gemini_backend.py
│ │ ├── mock_backend.py
│ │ └── registry.py
│ ├── backend_loader.py # Dynamic backend loading
│ └── scripts/ # TypeScript CoFHE bridge
│ └── cofhe_bridge.mjs
├── tests/ # Test suite
│ ├── test_crypto.py
│ ├── test_job_handler.py
│ ├── test_node_loop.py
│ ├── test_icl_client.py
│ ├── test_registry.py
│ ├── test_e2e.py
│ └── test_wallet.py
├── contracts/ # Solidity contract ABIs
├── pyproject.toml # Package configuration
├── docker-compose.yml # Docker orchestration
├── Dockerfile # Container image
└── README.md # This file
Docker
# Build image
docker build -t blindference-node .
# Run container
docker run -d \
--name blindference-node \
-e BLF_KEY_PASSWORD=secure_password \
-e BLF_ICL_ENDPOINT=https://icl.blindference.xyz \
-v /host/config:/root/.blindference \
blindference-node run
Security Model
Tier 0 (Mock Attestation)
- Software-only attestation with no hardware trust
- Quote: HMAC-SHA256 of nonce + runtime code hash
- For development only — nodes can be impersonated
Tier 1 (TPM 2.0)
- TPM-backed attestation with measured boot
- Hardware-bound identity
- Requires TPM 2.0 chip
Tier 2 (TEE / SGX / TDX)
- Intel SGX or AMD SEV enclave attestation
- Confidential computing — code and data encrypted in memory
- Remote attestation verified by ICL against manufacturer quoting enclaves
Slashing Conditions
Nodes may be slashed for:
- Failed attestation: Missing or expired certificate
- Missed heartbeat: No ICL heartbeat within 5 minutes
- Bad inference: Verifier consensus shows wrong result
- Timeout: Failed to submit result within execution window
Documentation
- Quickstart Guide — Step-by-step first node setup
- Attestation Guide — Mock, TPM, and TEE attestation
- Configuration — All config options and env vars
- Model Backends — Pluggable backend system
- Rewards & Slashing — How nodes earn and what gets them slashed
- Troubleshooting — Common issues and fixes
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
License
MIT License — see LICENSE for details.
Consensus Calibration Feedback
Every accepted inference job feeds into a long-term calibration loop that improves quorum accuracy over time:
| Signal | Source | Impact |
|---|---|---|
| Thumbs Up | User decrypts output, votes "accurate" | Increases confidence weight for leader's model provider |
| Thumbs Down | User decrypts output, votes "not accurate" | Flags potential false positives; triggers threshold review |
| Dispute Override | User overrides quorum rejection | Signals verifier pool may be too strict |
| Verdict Mismatch | Verifiers disagree with accepted leader | Reduces reputation of outlier verifier |
Nodes benefit from accurate calibration — a well-tuned quorum means fewer false rejections (more jobs accepted, more fees earned) and fewer false acceptions (less slashing risk).
Support
- Docs: docs.blindference.xyz
- Discord: Blindference Community
- Twitter: @blindference
- Issues: GitHub Issues
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file blindference_node-0.3.3.tar.gz.
File metadata
- Download URL: blindference_node-0.3.3.tar.gz
- Upload date:
- Size: 304.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b8cef7f477610c9450335cca786e127dd2eef152d904b3cd70c5f58aa8f229a
|
|
| MD5 |
4cefe347f02ab531ba6dd5aac25b0bf0
|
|
| BLAKE2b-256 |
fb0780bc146724b83773da46eca93fa89814dd25795584d2ef2480694cb32135
|
Provenance
The following attestation bundles were made for blindference_node-0.3.3.tar.gz:
Publisher:
publish.yml on AbhishekPanwarr/Blindference-node
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blindference_node-0.3.3.tar.gz -
Subject digest:
9b8cef7f477610c9450335cca786e127dd2eef152d904b3cd70c5f58aa8f229a - Sigstore transparency entry: 1674684233
- Sigstore integration time:
-
Permalink:
AbhishekPanwarr/Blindference-node@deabda879de21dcb88a08e17be3da89765fb8d43 -
Branch / Tag:
refs/tags/v0.3.3 - Owner: https://github.com/AbhishekPanwarr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@deabda879de21dcb88a08e17be3da89765fb8d43 -
Trigger Event:
push
-
Statement type:
File details
Details for the file blindference_node-0.3.3-py3-none-any.whl.
File metadata
- Download URL: blindference_node-0.3.3-py3-none-any.whl
- Upload date:
- Size: 304.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e71b928d4ba95ecadbdb1272d8455d16ff1ecf3b301db3360d2501439098b272
|
|
| MD5 |
88a2805337db0dd1cc2dbdf474fb2d89
|
|
| BLAKE2b-256 |
d83efe65a92ee349d1b39ffa3ccd12a717dad4ca3dc5b94b0cc397daed92eba5
|
Provenance
The following attestation bundles were made for blindference_node-0.3.3-py3-none-any.whl:
Publisher:
publish.yml on AbhishekPanwarr/Blindference-node
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
blindference_node-0.3.3-py3-none-any.whl -
Subject digest:
e71b928d4ba95ecadbdb1272d8455d16ff1ecf3b301db3360d2501439098b272 - Sigstore transparency entry: 1674684237
- Sigstore integration time:
-
Permalink:
AbhishekPanwarr/Blindference-node@deabda879de21dcb88a08e17be3da89765fb8d43 -
Branch / Tag:
refs/tags/v0.3.3 - Owner: https://github.com/AbhishekPanwarr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@deabda879de21dcb88a08e17be3da89765fb8d43 -
Trigger Event:
push
-
Statement type: