zkML + Circuit Stack
This is where AI meets cryptography. zkde.fi uses zero-knowledge machine learning to turn model inference into verifiable, policy-aware signals. The output of a model isn't a recommendation — it's a proof. And that proof can be verified on-chain before capital moves.
The system includes 31 Circom circuits, 2 EZKL ML models, and a bridge layer (ModelBridge) that converts arbitrary ONNX model outputs into on-chain-verifiable commitments via Garaga. Each piece serves a specific role in the pipeline.
The EZKL pipeline
Here's what happens when an ML model goes from training to on-chain verification:
flowchart LR ONNX["1. ONNX model<br/><i>trained offline</i>"] --> EZKL["2. EZKL compile<br/><i>quantize + circuit</i>"] EZKL --> KZG["3. KZG commitment<br/><i>weights → on-chain</i>"] KZG --> INFER["4. Inference<br/><i>private inputs</i>"] INFER --> G16["5. Groth16 proof<br/><i>correct execution</i>"] G16 --> BRIDGE["6. ModelBridge<br/><i>format bridge</i>"] BRIDGE --> GAR["7. Garaga verify<br/><i>on-chain in Cairo</i>"]
Walking through it:
Model training — a standard ML model is trained using whatever framework (PyTorch, scikit-learn, etc.) and exported as ONNX. Nothing special here — this is the model's normal lifecycle.
EZKL compilation — EZKL takes the ONNX model and converts it into a Halo2 arithmetic circuit. It quantizes the floating-point weights into fixed-point representations that work inside a ZK circuit. This is a build-time step, not a runtime step — the compiled artifacts are reusable.
KZG commitment — the model's quantized weights are committed via KZG polynomial commitment scheme. This commitment is registered on-chain, binding the model's identity to a specific set of weights. If someone swaps the model, the commitment won't match and verification fails.
Inference — at runtime, the model runs on user-provided inputs. The inputs stay private — they never leave the user's control. The prover generates a witness (inputs + intermediate values + outputs) that will be used to construct the proof.
Groth16 proof — EZKL generates a proof that the correct model, with the committed weights, ran correctly on the given inputs and produced the given output. This is the mathematical guarantee.
ModelBridge — a Circom circuit that takes the EZKL proof output and reformats it for Garaga's BN254 pairing check. Think of it as a format adapter between EZKL's proof system and Starknet's verification infrastructure.
On-chain verification — Garaga verifies the Groth16 proof natively in Cairo on Starknet. The verification is a single contract call that either passes or fails. No oracle, no committee, just math.
One important distinction: the "EZKL compilation" step happens at build time against pre-prepared model artifacts. The current stack relies on pre-built circuits and runtime proving services, not on-demand model compilation per request.
The two ML models
| Model | Architecture | Output classes | What it does |
|---|---|---|---|
| yield_forecast | Linear(12→32) → ReLU → Linear(32→16) → ReLU → Linear(16→4) | declining / stable / growing / surging | Predicts yield trajectory for a pool. Used in allocation decisions — "should capital go here?" |
| anomaly_detector | Linear(8→24) → ReLU → Linear(24→12) → ReLU → Linear(12→3) | safe / warning / critical | Detects anomalous pool behavior before capital enters. Safety check, not a trading signal. |
Both models are deliberately simple — small enough to compile into efficient ZK circuits, but expressive enough to capture the patterns that matter. A 50-layer transformer would be more powerful but impossible to prove in reasonable time. These models hit the sweet spot.
Both are compiled via EZKL into Halo2 circuits with KZG polynomial commitments. Proofs are verified on Ethereum Sepolia via the Halo2Verifier and bridged to Starknet via L1→L2 messaging or the ModelBridge circuit path.
The 13-circuit agent screening bundle
Before any execution path surfaces in Trade Desk, the relevant circuits from this bundle evaluate the action. Not all 13 fire every time — the system picks the circuits relevant to the action type. A swap triggers different circuits than a lending operation.
| # | Circuit | What it proves |
|---|---|---|
| 1 | RiskScore | Aggregate risk rating for a pool or position |
| 2 | AnomalyDetector | Whether pool behavior deviates from safe baselines |
| 3 | YieldOptimality | Whether the yield justifies the risk at current conditions |
| 4 | StrategyIntegrity | Whether the proposed strategy matches committed parameters |
| 5 | ExecutionIntegrity | Whether execution respected declared constraints (slippage, timing) |
| 6 | ImpermanentLossPredictor | Estimated IL exposure for LP positions |
| 7 | SlippageBound | Whether expected slippage stays within acceptable bounds |
| 8 | MEVResistanceProof | Whether the execution route has MEV protection characteristics |
| 9 | LiquidationRisk | Proximity to liquidation threshold for leveraged positions |
| 10 | CorrelationRisk | Cross-asset correlation risk in portfolio context |
| 11 | CreditEligibility | Whether collateral posture meets lending thresholds |
| 12 | SolvencyProof | Verifiable solvency attestation — "I can pay what I owe" |
| 13 | AgentReputationScore | Composite trust score from execution history |
Each circuit is compiled to WASM + zkey for fast client-side proof generation. The circuits are small enough to prove in seconds, which matters for UX — you don't want users waiting 30 seconds for a risk check.
FICO-pack verifiers
Five of these circuits have dedicated on-chain verifier contracts (the "FICO pack" — think of them as the credit score proofs of DeFi):
| Verifier | Address |
|---|---|
| SolvencyProofVerifier | 0x043b2...9c9b |
| RiskPassportTierVerifier | 0x05e71...7788 |
| TraderPerformanceVerifier | 0x04c80...0769 |
| StrategyIntegrityVerifier | 0x00c94...e549 |
| ExecutionIntegrityVerifier | 0x03bb2...873b |
The full 31-circuit set
Beyond the 13 agent screening circuits, the system has circuits for privacy, governance, bridging, and attestations:
| Category | Circuits | What they're for |
|---|---|---|
| Privacy | FullPrivacyWithdraw, FullPrivacyWithdrawHashed, FullPrivacyWithdrawWithChange, PrivateDeposit, PrivateWithdraw, PoolMembership | Shielded pool operations — deposits, withdrawals, membership proofs. See Privacy Rails. |
| Bridge | ModelBridge, ModelBridgeHeavy | Format adapters — bridge EZKL proof outputs to Garaga-verifiable Groth16 |
| Governance | private_vote | Cast a DAO vote without revealing voting power or direction |
| Position | TWAPPosition, RebalanceTimingCommitment | Time-weighted average price tracking and rebalance timing proofs |
| Attestation | HistoricalPerformanceAttestation, RobustnessCertificate, SafetyDiversification | Provable track record — "I performed well over 30 days" without revealing the equity curve |
| Threshold | BalanceAboveThreshold, TenureAboveThreshold | Selective disclosure — "my balance is above X" without revealing X |
| DeFi | CrossProtocolArbitrage, RiskPassportTier, TraderPerformanceProof | Cross-protocol risk and performance proofs |
Plus a Noir circuit (noir_ezkl_bridge/) for the Noir HONK proving lane — a different proving system that serves as an alternative verification path.
ModelBridge vs ModelBridgeHeavy
| ModelBridge | ModelBridgeHeavy | |
|---|---|---|
| Artifact size | ~2MB zkey | ~8MB zkey |
| Proving time | ~3–5 seconds | ~10–15 seconds |
| Use case | Default bridge for standard model outputs | Complex model outputs with more constraint capacity |
| Verifier | Same Garaga infrastructure | Same Garaga infrastructure |
Both produce Groth16 proofs. The difference is constraint capacity — ModelBridgeHeavy can handle larger model outputs at the cost of a heavier proving key and longer proving time.
The on-chain entry point for verifying bridged EZKL proofs: 0x037c4...626f (Starknet Sepolia).
zkML API endpoints
| Method | Endpoint | What it does |
|---|---|---|
POST | /api/v1/zkdefi/zkml/risk_score | Run risk score inference with proof generation |
POST | /api/v1/zkdefi/zkml/anomaly | Run anomaly detection |
POST | /api/v1/zkdefi/zkml/combined | Combined risk + anomaly in one call |
GET | /api/v1/zkdefi/zkml/status | zkML subsystem health |
GET | /api/v1/zkdefi/zkml/pool-safety | Pool safety snapshot (aggregated) |
POST | /api/v1/zkdefi/zkml/scan | General-purpose model scan |
GET | /api/v1/zkdefi/zkml/circuits | Circuit metadata — what's compiled and available |
Next: Privacy Rails · Proof Pipeline · API Reference