CLI
Command-line tool for model providers to register and certify models.
ZKFair is a trustless ML fairness auditing system built on:
┌─────────────────────────────────────────────────────────────────────────────┐│ ZKFAIR PROTOCOL FLOW │├─────────────────────────────────────────────────────────────────────────────┤│ ││ PHASE 1: MODEL REGISTRATION ││ ───────────────────────────── ││ Provider runs CLI to register model on-chain: ││ • Hash weights + dataset → commitments ││ • registerModel() with stake (0.0001 ETH) ││ • Generate ZK training proof → attestation service ││ • submitCertificationProof() → model CERTIFIED ││ ││ PHASE 2: INFERENCE & BATCHING ││ ───────────────────────────── ││ Users query the inference server: ││ • POST /predict → ONNX inference + signed receipt ││ • Queries stored with sequence numbers ││ • Auto-batch when: 100 queries OR 30 minutes ││ • commitBatch() → Merkle root on-chain ││ ││ PHASE 3: AUDITING ││ ──────────────── ││ Anyone can challenge a batch: ││ • requestAudit(batchId) with stake (0.00005 ETH) ││ • Contract generates random sample indices ││ • Provider has 24h to respond with ZK fairness proof ││ • submitAuditProof() → PASSED or FAILED ││ • Missing deadline → provider slashed ││ ││ PHASE 4: FRAUD DETECTION ││ ──────────────────────── ││ Users verify their receipts: ││ • Receipts stored locally (IndexedDB) ││ • Sentinel verifies against on-chain Merkle roots ││ • Dispute types: ││ - NON_INCLUSION: Query never batched ││ - FRAUDULENT_INCLUSION: Merkle proof fails ││ • Provider slashed, user compensated ││ │└─────────────────────────────────────────────────────────────────────────────┘CLI
Command-line tool for model providers to register and certify models.
Server
Inference server with batching, receipts, and audit handling.
Web App
User interface with Sentinel fraud detection.
SDK
TypeScript SDK for providers (ProviderSDK) and clients (BrowserSDK).
Contracts
Solidity contracts for model registry, batching, and disputes.
ZK Circuits
Noir circuits for training certification and fairness audits.
// Provider prepares artifactsmy-model/├── weights.bin // Serialized model weights├── dataset_encoded.csv // Label-encoded training data├── fairness_threshold.json // { "threshold": 10 }└── model.onnx // ONNX model for inference
// CLI computes commitmentsweightsHash = poseidon(weights)datasetRoot = merkleRoot(dataset)
// Register on-chainregisterModel(name, weightsHash, datasetRoot, threshold)// User requests inferencePOST /predict { modelHash, input }
// Server processesprediction = onnxSession.run(input)seqNum = db.insert({ modelId, features, prediction, timestamp })receipt = sign({ seqNum, dataHash }, providerKey)
// Auto-batchif (unbatchedCount >= 100 || oldestQuery > 30min) { root = merkleRoot(queries) commitBatch(modelId, root, seqRange)}// Challenger requests auditrequestAudit(batchId) // stakes 0.00005 ETH
// Contract generates random samplessampleIndices = random(0..queryCount, 10)
// Provider generates ZK proofproof = fairnessAuditCircuit({ weights, samples, merkleProofs, threshold})
// Submit via attestation servicesubmitAuditProof(auditId, attestationHash, signature)// User verifies receiptbatch = findBatchForSeqNum(seqNum)
if (!batch && gracePeriodPassed) { // FRAUD: Non-inclusion disputeNonInclusion(receipt)}
proof = fetchProof(providerUrl, seqNum)if (!verifyMerkleProof(leafHash, proof, batch.root)) { // FRAUD: Invalid proof disputeFraudulentInclusion(batchId, seqNum)}| Component | Trust Level |
|---|---|
| Smart contract | Immutable, verified code |
| Attestation service | TEE-based, signs honestly |
| ZK circuits | Mathematically sound |
| Users | Store receipts honestly |
| Threat | Mitigation |
|---|---|
| Provider omits queries | Merkle proofs + user receipts |
| Provider tampers data | Signed receipts + verification |
| Provider uses unfair model | ZK fairness proofs |
| Provider ignores audits | Deadline + slashing |
| Challenger spam | Audit stake required |
| Parameter | Value | Description |
|---|---|---|
PROVIDER_STAKE | 0.0001 ETH | Required to register model |
AUDIT_STAKE | 0.00005 ETH | Required to request audit |
DISPUTE_STAKE | 0.0001 ETH | Required to file dispute |
AUDIT_DEADLINE | 24 hours | Provider response window |
GRACE_PERIOD | 1 hour | Time to batch queries |