Blind Bazaar is a privacy-preserving AI ad-inventory auction. An advertiser agent negotiates with one or two publisher agents, then the accepted deal is verified by a real Midnight Compact contract using zero-knowledge proofs.
The demo shows a simple idea: participants can prove an agreed CPM is within the advertiser's private ceiling and the publisher's private floor, and that delivered quality meets the promised threshold, without revealing those private limits.
Hackathon demo status: the end-to-end flow works on a local Midnight development network. It is not a mainnet deployment and it does not move real money.
Hosted demo: https://blindbazaar-demo.duckdns.org
The app is hosted on Google Compute Engine and served over HTTPS by Caddy. The URL is available while the demo VM is running. Midnight proof generation happens on a VM-local Midnight development network; its node, indexer, and proof server are not exposed to the public internet.
- Streams a live, Groq-powered negotiation between advertiser and publisher agents.
- Detects an accepted deal in the agent transcript.
- Generates a Midnight fairness proof and delivery proof against a deployed Compact contract.
- Shows real contract and transaction identifiers in the browser after verification succeeds.
- Lets the viewer download a privacy-safe JSON proof receipt containing only public verification metadata.
- Stores completed transcript sessions locally in the browser.
Browser UI
│ live Server-Sent Events
▼
Express app + Groq negotiation agents
│ verified deal input
▼
Midnight.js verifier + local wallet
│ ZK proof requests
▼
Local Midnight node + indexer + proof server (Docker)
│
▼
BBoard Compact contract
The full architecture diagram shows the public HTTPS edge, Google Cloud VM, Groq-powered negotiation flow, private witness boundary, Midnight.js verifier, and VM-local Docker services. See architecture notes for component responsibilities and network boundaries.
| Two-publisher AI auction | Midnight proof results |
|---|---|
![]() |
![]() |
The proof receipt and the UI never include the private witness values:
- advertiser maximum CPM
- publisher CPM floor
- publisher's actual delivery quality
- wallet seeds, recovery phrases, or private state
The browser displays the negotiated offer because the agents state it publicly in the transcript. The contract proves only the pass/fail conditions. The downloaded receipt contains the contract address, two transaction IDs, verification verdicts, publisher ID, and timestamp—nothing else.
- Node.js 22 or newer
- Docker Desktop with at least 4 GB allocated
- Compact compiler 0.31.1
- A free Groq API key
cd /path/to/blind-bazaar
cp .env.example .envSet GROQ_API_KEY in .env. Never commit that file.
Both generated binding directories are local build output and are intentionally ignored by Git.
cd contract
npm install
compact compile src/bboard.compact src/managed/bboard
cd ../blind-bazaar-contract
npm install
npm run compilecd /path/to/blind-bazaar/blind-bazaar-contract
docker compose up -d
docker compose ps
npm run deployAll three services must be healthy: node, indexer, and proof-server.
In a second terminal:
cd /path/to/blind-bazaar
npm install
npm startOpen http://localhost:3000 and click Launch auction. A full run normally takes about one minute: agent negotiation, wallet sync, fairness proof, then delivery proof.
The contract source is contract/src/bboard.compact.
| Circuit | Private witnesses | Public result |
|---|---|---|
verifyCredential |
None currently | Checks that a supplied 32-byte credential value is nonempty. This is a deliberate placeholder, not production identity verification. |
verifyDealFairness |
Advertiser max CPM; publisher floor CPM | Proves the proposed CPM is within both private bounds, updates lastDealValid, and increments dealCount. |
verifyDelivery |
Publisher actual quality | Proves actual quality meets the promised quality and updates lastDeliveryValid. |
Quality ratings shown as decimals, such as 7.8, are represented in the proof as integer tenths (78). Both sides use the same scale, so the comparison is preserved.
public/ Browser UI and proof-receipt download
server/
agents/ Groq advertiser and publisher agents
negotiation.js Streams negotiation and requests verification
midnightReal.js Starts the real Midnight verifier process
index.js Express server and SSE endpoint
contract/
src/bboard.compact Compact source of truth
src/witnesses.ts Private witness definitions
blind-bazaar-contract/
src/deploy.ts Deploys BBoard to the selected Midnight network
src/verify-deal.ts Generates fairness and delivery proof transactions
docker-compose.yml Local node, indexer, and proof-server
Other top-level bboard-*, deploy-app, api, and my-deploy folders are retained scaffolds and experiments. They are not required for the Blind Bazaar demo path above.
| Command | Purpose |
|---|---|
npm start |
Start the Express application on port 3000. |
cd blind-bazaar-contract && docker compose up -d |
Start the local Midnight services. |
cd blind-bazaar-contract && npm run compile |
Generate the deployment-side Compact bindings. |
cd blind-bazaar-contract && npm run deploy |
Deploy the contract to the selected network; fresh clones default to local devnet. |
cd blind-bazaar-contract && npm run verify-deal -- --help |
Show the real verifier input format. |
cd blind-bazaar-contract && docker compose down |
Stop the local Midnight services. |
- The deployed contract used by this demo is on a local Midnight development network. Its address changes with a fresh local chain.
- The green
$0.05 demo rewardis UI-only. There is no payment or escrow contract and no token transfer to a publisher. verifyCredentialis intentionally a placeholder until a real credential scheme is chosen.- The Groq key remains on the server; do not expose it in browser code, screenshots, or Git history.
- This app uses Server-Sent Events. Static hosts such as GitHub Pages cannot run it. The hosted demo uses Google Compute Engine, Caddy, and DuckDNS; only HTTPS is public, while the Midnight node, indexer, and proof server remain VM-local.
Before pushing or changing repository visibility:
- Confirm
.env,.midnight-state.json,.midnight-wallet-state/,midnight-level-db/, and generated bindings are ignored. - Run
git status --shortand ensure no runtime wallet state is staged. - Never add a Groq API key, wallet seed, recovery phrase, or private-state password to Git.
- Keep the repository's old Preview wallet retired; do not reuse a wallet whose seed appeared in a public repository.
No license has been selected yet. Add one before inviting external reuse of the code.


