Mohar
Prove who had the exam paper before the exam
Created on 18th October 2026
•
Mohar
Prove who had the exam paper before the exam
The problem Mohar solves
India has a paper leak problem. 41 recruitment exam leaks across 15 states in five years, about 1.4 crore (14 million) applicants affected. This May NEET-UG was cancelled and re-held over a leak. And every leak turns into the same fight about time: a "leaked paper" goes round Telegram the night before, and afterwards nobody can prove when it actually existed. Screenshots get called fake, and the only other clock is the exam body's own server, owned by the party being accused.
Mohar gives everyone a clock that neither the exam body nor the leakers control.
- Exam bodies seal a salted fingerprint of every question before the exam. The seal can't be edited or deleted, not even by them. At the bell they reveal the paper in one go.
- Anyone who gets a "leaked paper" seals one-way fingerprints of it from their phone. The questions and their identity never leave the device, and every witness comes from a fresh, unlinkable wallet.
- Everyone then sees the verdict: who held real questions before the exam, which rumours were fake, and which claims came too late.
It works today for any exam, even without the exam body: anyone can add an "open exam" and check witnesses against the official paper once it's out. Exam bodies prove which wallet is theirs from their own website (/.well-known/mohar.json), so trust doesn't depend on me. And if the site is ever blocked, anyone can rebuild every verdict with npx mohar-verify <exam> or one saved HTML page. Everything works in English and Hindi, on a phone.
Challenges I ran into
extendEntity(fromDays(14))means "14 days from now", not "+14 days". My keep-alive button looked like it worked but added about a minute. I caught it by readingexpiresAton chain, and now I compute the target block myself.readonlydoesn't stop the owner deleting. So seals are created and handed to a dead address in the same batch, and nobody can delete them, me included.- Big papers failed with "Execution error without revert data". It turned out to be the RPC's 256 KB body limit (about 128 KB of payload, since hex doubles it). I now pack seals and reveals into batches under 100 KB, and a 900-question bilingual paper seals fine.
- Keyless read budget. I burned through it (~100 queries per IP) while testing. I rebuilt the exam page to use one query instead of four, throttled live refetches, and moved server reads to a keyed proxy.
- Making "before the exam" honest. The exam body sets the announced start, so a dishonest one could push it later to make late claims look early. The deadline is now the earlier of the announced start and the earliest reveal block.
- Funding witnesses without linking them. A shared wallet would tie every leak report together. Each seal now uses a brand-new wallet, funded by a small drip that needs a proof-of-work puzzle and only funds empty wallets, so it can't be farmed.
- Hindi. Matras had to survive normalisation, and my own bilingual test caught that
प्रश्न १। …didn't match because I only stripped English numbering. Fixed and proven on chain. - Getting test GLM. It took longer than writing my first entity: the faucet crashed without MetaMask unlocked, and the cooldown is per connected wallet.
Tracks Applied (5)
Censorship Resistance
Open Source
Privacy
Security
Best Indian Use Case
Technologies used
