cuHacking 7 Winner - MLH Best Use of MongoDB Atlas
Provenance is a camera-to-chain photo authenticity system. Every photo is cryptographically signed at the moment of capture and anchored to the Solana blockchain - so anyone, anywhere, can later prove that an image is the real, unmodified original.
Unlike AI-detector guesswork, Provenance never guesses. A photo either matches an unforgeable on-chain record, or it doesn't. It doesn't try to spot fakes - it proves reals.
- 📸 Sign at capture: The app hashes the photo (SHA-256), builds a canonical 72-byte manifest, and signs it with an Ed25519 key that is generated on-device, stored in the hardware secure store, and never leaves the phone.
- ⛓️ Anchor on-chain: The backend validates the signature, then submits it to our Solana program, which re-verifies the signature on-chain and mints a content-addressed record (PDA seeded by the photo's hash). Duplicates are rejected by construction. Every attestation is visible on the public Solana Explorer.
- 🔍 Verify anywhere: Anyone can check a photo - the verifier derives the on-chain address straight from the file's hash and reads the chain directly. No database trust required, no account needed.
- 👁️ Survives recompression: A perceptual hash (64-bit DCT pHash) is computed from the exact signed bytes at ingest and baked into the immutable on-chain record - so a recompressed or resized repost can still be traced back to its verified original via MongoDB Atlas Vector Search.
- 🧾 Rebuildable registry: The browsable registry is a Mongo mirror of the chain. A reindex script can rebuild it from scratch by scanning on-chain accounts - the chain is always the source of truth.
CAPTURE PATH VERIFY PATH
┌──────────────────────┐ ┌──────────────────────┐
│ Device (app) │ │ App / Chrome │
│ camera → SHA-256 │ │ hash photo / URL │
│ Ed25519 sign │ └──────────┬───────────┘
│ 72-byte manifest │ │
└──────────┬───────────┘ derive PDA ["photo", sha256]
│ POST /attest │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Backend (Node) │ │ Solana read │──► 🟢 GREEN (byte-exact)
│ verify sig │ │ PDA exists? decode │──► ⚪ GREY (no record)
│ compute pHash │ └──────────┬───────────┘
│ fee-payer sponsor │ miss │ POST /verify
└─────┬───────────┬────┘ ▼
│ 2-ix tx │ index ┌──────────────────────┐
▼ ▼ │ Atlas Vector │
┌───────────┐ ┌───────────┐ │ Search (pHash ANN) │
│ Solana │ │ Mongo │ │ → chain-confirm ────│──► 🟠 AMBER (recompressed)
│ program │╌►│ mirror │ └──────────────────────┘
│ re-verify│ │ registry │
│ mint PDA │ └───────────┘
└───────────┘
chain is the source of truth ─ ╌► reindex: getProgramAccounts replays every
on-chain record to rebuild the Mongo mirror from scratch
Every verification returns exactly one of three honest answers - never a fake "verified":
| Tier | Meaning | Backed by |
|---|---|---|
| 🟢 GREEN | Byte-exact match - unmodified since capture | Direct on-chain PDA read |
| 🟠 AMBER | Recompressed/resized version of a verified original | pHash vector search, then chain-confirmed before display |
| ⚪ GREY | No record found - not a judgment of authenticity | - |
- Take a photo with the in-app camera (pinch-to-zoom, tap/hold-to-focus, flash).
- Watch the forensic checklist run live: SHA-256 → manifest signed → anchoring to Solana.
- Get the ANCHORED card with the real transaction and a Solana Explorer link.
- Pick a photo or paste an image URL.
- The verifier hashes it, reads the chain, and renders the GREEN / AMBER / GREY verdict - AMBER shows the submitted image side-by-side with the attested original and the perceptual distance.
- Browse recent attestations (hash, time, device, tx) with verified/unverified status badges; search by hash or device; tap into full record detail.
- Badge scanner: overlays a live GREEN / AMBER / GREY badge on every photo in a feed - auto-runs on the bundled Instagram-style demo feed (
extension/demo-feed/), opt-in on any other page via the popup's SCAN THIS PAGE toggle. Click a badge for the full verdict card. - Right-click any single image → Verify with Provenance → the same GREEN / AMBER / GREY verdict card, with perceptual distance and a Solana Explorer link.
- App: Expo (React Native) · expo-router · NativeWind · TypeScript
- Chain: Solana devnet · Anchor (Rust) program · content-addressed PDAs (
["photo", sha256]) · Ed25519 precompile verification (deployed program:EoWdD…jZ8g) - Backend: Node/TS · MongoDB Atlas + Atlas Vector Search (pHash ANN) · sharp (image decode)
- Crypto: SHA-256 · Ed25519 (tweetnacl + expo-secure-store) · 64-bit DCT perceptual hash (our own implementation, shared across device/backend/web)
- Extension: Chrome MV3 · feed badge overlay + right-click verify · zero-dependency demo feed server
npm install
npx expo start # scan the QR with Expo Gocd backend
npm install
npm start # POST /attest, /verify, /lookup/:sha256, /recent on :8787Already built and deployed to devnet (EoWdD…jZ8g) - nothing to run for the demo.
To rebuild: cd program && ./build.sh (see program/README.md; don't use anchor build).
chrome://extensions → Developer mode → Load unpacked → select extension/.
Demo feed: node extension/demo-feed/serve.mjs → http://localhost:8788 (see extension/demo-feed/README.md for staging GREEN/AMBER/GREY posts).
npm test # pHash + signing contract (also runs as a pre-push hook + CI)
cd backend && npm test # lookup, Mongo indexing, AMBER matching, /verify tiersFor the app (all optional - safe demo defaults):
EXPO_PUBLIC_BACKEND_URL(defaulthttp://localhost:8787; Android emulator:http://10.0.2.2:8787)EXPO_PUBLIC_USE_FAKE_REGISTRY(defaulttrue; setfalseto hit the real backend + chain)
For the backend:
MONGODB_URI- MongoDB Atlas connection string (M0 free tier works)SOLANA_RPC_URL(default: public devnet endpoint; use a free Helius/QuickNode key to avoid rate limits)FEE_PAYER_KEYPAIR_PATHorFEE_PAYER_SECRET_KEY- devnet fee-payer walletPORT(default8787)