Skip to content

Architecture Overview

ZKFair is a trustless ML fairness auditing system built on:

  • Cryptographic commitments to model weights and training data
  • ZK proofs for training certification and continuous auditing
  • On-chain batch commitments with Merkle trees
  • Client-side fraud detection via receipt verification
  • Economic incentives through staking and slashing
┌─────────────────────────────────────────────────────────────────────────────┐
│ 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 artifacts
my-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 commitments
weightsHash = poseidon(weights)
datasetRoot = merkleRoot(dataset)
// Register on-chain
registerModel(name, weightsHash, datasetRoot, threshold)
// User requests inference
POST /predict { modelHash, input }
// Server processes
prediction = onnxSession.run(input)
seqNum = db.insert({ modelId, features, prediction, timestamp })
receipt = sign({ seqNum, dataHash }, providerKey)
// Auto-batch
if (unbatchedCount >= 100 || oldestQuery > 30min) {
root = merkleRoot(queries)
commitBatch(modelId, root, seqRange)
}
// Challenger requests audit
requestAudit(batchId) // stakes 0.00005 ETH
// Contract generates random samples
sampleIndices = random(0..queryCount, 10)
// Provider generates ZK proof
proof = fairnessAuditCircuit({
weights, samples, merkleProofs, threshold
})
// Submit via attestation service
submitAuditProof(auditId, attestationHash, signature)
// User verifies receipt
batch = 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)
}
ComponentTrust Level
Smart contractImmutable, verified code
Attestation serviceTEE-based, signs honestly
ZK circuitsMathematically sound
UsersStore receipts honestly
ThreatMitigation
Provider omits queriesMerkle proofs + user receipts
Provider tampers dataSigned receipts + verification
Provider uses unfair modelZK fairness proofs
Provider ignores auditsDeadline + slashing
Challenger spamAudit stake required
ParameterValueDescription
PROVIDER_STAKE0.0001 ETHRequired to register model
AUDIT_STAKE0.00005 ETHRequired to request audit
DISPUTE_STAKE0.0001 ETHRequired to file dispute
AUDIT_DEADLINE24 hoursProvider response window
GRACE_PERIOD1 hourTime to batch queries
  • Failed audit → Provider loses stake to challenger
  • Missed deadline → Provider slashed
  • Valid dispute → Provider slashed, user compensated