A privacy-preserving on-chain neural network training application built on Aztec Network. Draw digits, run inference privately, and submit training updates that improve the shared model β all with zero-knowledge proofs.
- π§ Three neural network architectures β Single Layer (64β10), MLP (64β16β10), CNN+GAP
- π Private training β gradient updates computed client-side, committed on-chain via hash
- βοΈ Draw-to-predict β canvas input processed through MNIST pipeline, classified by the contract
- β½ Sponsored fee payments β gasless transactions through SponsoredFPC
- π Network switching between Testnet and local network
- Node.js >= 22.0.0
- Yarn package manager
- Foundry (for Anvil, the local L1 chain)
git clone <repo-url>
cd aztec-hyve-training
yarn install# Install the Aztec version manager
bash -i <(curl -s https://install.aztec.network)
# Install the matching Aztec version (see package.json config.aztecVersion)
aztec-up install $(node -e "console.log(require('./package.json').config?.aztecVersion ?? 'latest')")
# Terminal 1: Start Anvil (local L1 chain)
anvil --host 0.0.0.0 -p 8545 --block-time 12
# Terminal 2: Start the Aztec local network
aztec start --local-network --l1-rpc-urls http://localhost:8545
# Terminal 3: Build, deploy, and run
yarn build && yarn deploy-contracts:local-network && yarn devNote: The
aztec-up installstep requires Foundry to not be running. If it fails with "anvil is currently running", stop Anvil first, install, then restart it.
The application will be available at http://localhost:3000
yarn build-contracts # Compile all Noir contracts + generate TS bindings
yarn test:nr # Run Noir contract tests (aztec test)yarn deploy-contracts # Deploy to local network (default)
yarn deploy-contracts:local-network # Deploy to local network
yarn deploy-contracts:testnet # Deploy to testnet (needs SPONSOR_FPC_ADDRESS or SPONSOR_FPC_SALT in .env)
yarn deploy-contracts:all # Deploy to bothDeployed addresses are written to:
config/deployed.local.jsonβ local network (gitignored)config/deployed.jsonβ testnet (committed)
yarn dev # Start Vite dev server
yarn build # Build contracts + app
yarn build-app # Build app only
yarn build-app:ci # CI build (reduced memory)
yarn serve # Preview production buildyarn test:js # Run JS unit tests (vitest)
yarn test:nr # Run Noir contract tests
yarn test:e2e # Run Playwright E2E tests (deploys + builds first)
yarn test:e2e:local-network # Run E2E tests against a running local network
yarn lint # Check formatting (ESLint + Prettier)
yarn lint:fix # Auto-fix formattingaztec-hyve-training/
βββ contracts/ # Noir smart contracts
β βββ zkml/ # Shared zkml library (forward pass, backprop, packing)
β β βββ src/
β β βββ architectures/ # arch_64_10, arch_64_16_10, arch_cnn_gap
β β βββ test/ # Pure unit tests for all architectures
β β βββ *.nr # conv, pooling, relu, softmax, packing, hash
β βββ single_layer_contract/ # On-chain single-layer network (64β10)
β βββ multi_layer_perceptron/ # On-chain MLP (64β16β10)
β βββ cnn_gap_contract/ # On-chain CNN+GAP network
βββ scripts/
β βββ deploy.ts # Deployment script (local network + testnet)
β βββ build-contracts.ts # Contract compile + codegen helper
β βββ pretrained-weights.ts # Pre-trained weight loaders
β βββ weight-packing.ts # 9-bit weight packing utilities
βββ config/
β βββ deployed.json # Testnet deployment addresses (committed)
β βββ deployed.local.json # Local deployment addresses (gitignored)
βββ src/
β βββ artifacts/ # Generated contract TypeScript bindings
β βββ aztec-wallet/ # Modular Aztec wallet library
β β βββ adapters/ # Browser wallet adapters (Azguard)
β β βββ components/ # ConnectButton and modals
β β βββ connectors/ # Wallet connector implementations
β β βββ hooks/ # useAztecWallet, useConnectModal, etc.
β β βββ providers/ # AztecWalletProvider
β β βββ services/ # PXE client service
β β βββ signers/ # Account signing implementations
β β βββ store/ # Zustand stores
β β βββ types/ # Configuration types
β βββ components/ # React UI components
β β βββ canvas/ # Drawing canvas and controls
β β βββ home/ # Prediction panel, architecture selector
β β βββ settings/ # Config panel
β β βββ shapley/ # Shapley value visualisation
β β βββ ui/ # Primitive components (Button, Card, Dialog, etc.)
β βββ config/
β β βββ contracts.ts # Contract address registry
β β βββ walletConfig.ts # Aztec wallet configuration
β β βββ networks/ # Network constants
β βββ hooks/
β β βββ mutations/ # useTrainOnChain (on-chain training mutation)
β β βββ network/ # useAztecNode, useNetworkStore
β β βββ useNeural.ts # Prediction + training orchestration
β β βββ useNetworkStatus.ts # Node connection status
β β βββ useToast.ts # Toast notifications (Zustand)
β βββ pages/
β β βββ Home.tsx # Main draw-predict-train page
β β βββ DocsPage.tsx # Documentation page
β βββ services/
β β βββ TrainingService.ts # Aztec node + contract interaction service
β β βββ aztec/ # Low-level Aztec client helpers
β β βββ core/ # Image processor, neural trainer (JS-side)
β βββ store/ # Global Zustand stores
β βββ styles/ # Tailwind CSS + CVA theme
β βββ utils/ # Utility functions
βββ tests/
βββ unit/
β βββ config/ # contracts.ts tests
β βββ services/ # TrainingService, ImageProcessor, NeuralTrainer tests
βββ e2e/
βββ app.test.ts # Unauthenticated smoke tests
βββ local-network/ # Connected-wallet E2E tests
Training on Aztec uses a hash-commitment pattern to prevent race conditions:
- Client computes the forward pass + backward pass (gradient update) entirely off-chain inside the PXE prover
submit_training_input(private) β packs current weights, trains, repacks new weights, enqueues a public call with the hash of new weightsapply_training_update(public,only_self) β verifies the committed hash and writes the new packed weights to public storage
This means the gradient computation is proven correct by the ZK circuit, and the public state update is atomic and replay-safe.
| Contract | Architecture | Weights | Biases |
|---|---|---|---|
SingleLayerContract |
64β10 linear | 640 | 10 |
MultiLayerPerceptronContract |
64β16β10 (ReLU) | 1,184 | 26 |
CNNGAPContract |
Conv(4Γ4Γ3)βReLUβGAPβFC(3β10) | 78 | 13 |
Weights are stored packed (9-bit, 28 values per Field) to minimise on-chain storage.
| Wallet | Description | Use Case |
|---|---|---|
| Embedded | Keys generated and stored in browser | Quick testing |
| Azguard | Browser extension wallet | Production, user-controlled keys |
- Install the Azguard browser extension
- Navigate to Settings β Fee Configuration
- Select FPC in the "Pay fee with" dropdown
- Click "Create New FPC" and enter the Sponsored FPC address:
0x1586f476995be97f07ebd415340a14be48dc28c6c661cc6bdddb80ae790caa4e
To add support for a new browser wallet (e.g., Obsidian):
- Create
src/aztec-wallet/adapters/obsidian/withObsidianAdapter.ts,ObsidianWalletService.ts, andindex.ts - Implement
IBrowserWalletAdapterin the adapter class - Register it in
src/aztec-wallet/config/aztecWallets.ts - Add
'obsidian'to theaztecWalletsarray insrc/config/walletConfig.ts
No changes needed to hooks, providers, or BrowserWalletConnector β the adapter pattern handles all wallet-specific logic.
| Network | Node URL | Usage |
|---|---|---|
| Local Network | http://localhost:8080 |
Development |
| Testnet | https://rpc.testnet.aztec-labs.com/ |
Public testnet |
This project uses Tailwind CSS v4 and Radix UI Primitives.
All Tailwind classes must be defined in a styles object at the top of the component β never inline:
// β
Correct
const styles = {
container: 'flex flex-col gap-4',
title: 'text-lg font-semibold text-default',
} as const;
// β Wrong
<div className="flex flex-col gap-4">MIT β see LICENSE for details.
Built with Aztec Network