Verifying Reality in the Age of AI
Spartahack 11 | Track: Roots and Renewal (Social Good)
RealityCheck is a decentralized media registry that acts as a notary public for digital content. By using Solana blockchain technology, it provides immutable Proof of Existence and Proof of Authorship for photos and videos to combat artificially modified media.
RealityCheck/
├── program/ # Solana/Anchor smart contract
├── app/ # Next.js web application
└── extension/ # Chrome browser extension
| Component | Technology |
|---|---|
| Blockchain | Solana (Devnet) |
| Smart Contract | Anchor Framework (Rust) |
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS |
| Web3 Client | @solana/wallet-adapter-react, @coral-xyz/anchor |
| Hashing | Web Crypto API (SHA-256) |
| Extension | Chrome Manifest V3 |
| Icons | Lucide React |
- Rust (latest stable)
- Solana CLI (v1.17+)
- Anchor Framework (v0.32.1+)
- Node.js (v18.18+ recommended)
- Yarn (recommended for
program/) and/or npm
# Install Solana CLI
sh -c "$(curl -sSfL https://release.solana.com/v1.17.0/install)"
# Configure for Devnet
solana config set --url devnet
# Generate a new keypair (if you don't have one)
solana-keygen new
# Airdrop some SOL for testing
solana airdrop 2cd program
# Install dependencies
yarn install
# Build the program
anchor build
# Get your program ID
solana address -k target/deploy/reality_check-keypair.json
# IMPORTANT (only if you deploy your own program):
# If your program ID changes, update it in:
# - Anchor.toml (both localnet and devnet)
# - programs/reality_check/src/lib.rs (declare_id! macro)
# - ../app/src/lib/idl.ts (PROGRAM_ID + IDL.address)
# Deploy to Devnet
anchor deploy
# Run tests
anchor testAfter building the program, the IDL is generated at:
program/target/idl/reality_check.json
Copy the JSON contents into the IDL object in app/src/lib/idl.ts. The format matches directly—just paste and replace the existing object.
Also update the PROGRAM_ID if your program ID changed.
Note: This repo already includes a working
IDL+PROGRAM_IDfor the current deployed program. You only need to do this step if you rebuild/redeploy or modify the program.
cd app
# Install dependencies
npm install
# Start development server
npm run devThe app will be available at http://localhost:3000
- Open Chrome and navigate to
chrome://extensions/ - Enable "Developer mode" (toggle in top right)
- Click "Load unpacked"
- Select the
extension/folder - The RealityCheck icon should appear in your toolbar
The Next.js app also serves a ready-to-install zip at app/public/extension.zip (and the web UI links to it as /extension.zip).
Note: The extension is currently configured to call a hosted API (
https://reality-check-deployment.vercel.app/api/verify). To use a local dev server, changeREALITYCHECK_API_BASEinextension/content.js(and the matching constant inextension/background.js).
- Upload: User drops an image into the web app
- Hash: SHA-256 hash is calculated client-side (browser)
- IPFS: Image is uploaded to IPFS (mocked in demo)
- Sign: User signs a Solana transaction with their wallet
- Store: Hash + metadata stored on-chain in a PDA
- Check: User uploads an image to verify (or uses extension)
- Hash: Same SHA-256 hash is calculated
- Lookup: PDA is derived from hash for O(1) lookup
- Result: Blockchain data returned (author, timestamp, etc.)
Images are stored in PDAs derived from:
seeds = [b"image", &image_hash.as_bytes()[..32]]This allows instant lookup by hash without iteration. The program still stores and validates the full 64-character SHA-256 hex string; the PDA uses the first 32 bytes of the string to fit seed limits.
RealityCheck uses SHA-256 cryptographic hashing on the raw file bytes. This means:
| Scenario | Same Hash? |
|---|---|
| Same exact file | Yes |
| JPEG vs PNG of same image | No |
| Same JPEG at different quality levels | No |
| Same file re-saved (even same format) | Often No |
| Screenshot of the image | No |
| Cropped or resized | No |
| Same file, different filename | Yes |
Why different formats produce different hashes:
Each image format encodes pixels differently (JPEG uses lossy DCT compression, PNG uses lossless deflate, etc.). Even metadata differences like EXIF data or timestamps will change the hash. A single bit difference produces a completely different SHA-256 hash.
This is intentional. For Proof of Existence and Proof of Authorship, you want to verify the exact original file. Any modification—even minor compression—should be detectable.
Best practice for users: Register the original file directly from your camera or source. The exact file you register is what can be verified. If you convert, compress, or edit the image later, it will produce a different hash and won't match the blockchain record.
This design is ideal for photographers, journalists, and creators who need to prove they possess the original, unmodified file.
- Immutable Timestamping: Proves an image existed at a specific time
- Censorship Resistance: Records stored on blockchain, no central authority
- O(1) Lookup: PDA-based storage allows instant verification by hash
- Browser Extension: Verify any image on the web with one click
- Dark Mode UI: Modern, accessible interface
Verify an image hash against the blockchain.
Query Parameters:
hash(required): 64-character hex SHA-256 hash
Response (verified):
{
"verified": true,
"data": {
"author": "5FHw...abc",
"timestamp": 1706745600,
"imageHash": "abc123...",
"ipfsCid": "Qm..."
}
}Response (not found):
{
"verified": false,
"message": "Image not found in blockchain registry"
}Notes:
- The API route is implemented in the Next.js app and queries Solana Devnet.
- CORS is enabled (including
OPTIONS) so the browser extension can call it.
The smart contract returns the following errors:
| Code | Name | Description |
|---|---|---|
| 6000 | InvalidHashLength | Hash must be exactly 64 hex characters |
| 6001 | InvalidCidLength | IPFS CID must be ≤100 characters |
Attempting to register the same image twice will fail with an "account already in use" error (handled gracefully in the UI).
# Start local Solana validator
solana-test-validator
# In another terminal
cd program
anchor testTip: If you want to run fully local (validator + program + app), set
cluster = "localnet"under[provider]inprogram/Anchor.toml, then rebuild/deploy locally and update the appPROGRAM_ID/IDL.
The extension uses plain HTML/JS/CSS with no build step. Simply edit the files and reload the extension in Chrome.
Heads up: websites often resize/recompress images, which changes the bytes (and therefore the SHA-256 hash). The extension verifies the exact bytes it fetches from the page URL, so it may not match the original file a creator registered.
Rather than enforcing a single authority, RealityCheck is trust-agnostic. Anyone can curate or publish their own database of credible uploaders, and users are free to choose which trust lists they rely on. If you don’t trust one source list, you can switch to another, or create your own.
- Adding support for using alternative database authorities
- Implementing a default authority for credible uploaders made up of journalist, professional photographers, and news outlets