GHOST
Your assets. Your identity. Your privacy.
GHOST is a zero-knowledge wallet identity protocol for Solana. A user links any number of private ghost identities to one wallet and proves statements like
“I hold at least 1,000 of token
M”
to a third-party app without revealing their wallet address, their exact balance, or any of their other holdings.
Status: research-grade, working MVP. It has not been independently audited. Do not rely on it to protect high-value assets or people at risk until it has been reviewed.
What is real
| Component | Implementation |
|---|---|
| Proving system | Groth16 over BN254, Circom 2.2 circuit (6,175 constraints), snarkjs 0.7 |
| Trusted setup | Phase 1: PSE Perpetual Powers of Tau (80 contributions). Phase 2: local single-party contribution + beacon (must be replaced by an MPC ceremony for production) |
| Hash / commitments | Poseidon (circomlib parameters), domain-separated |
| Authenticated state | Ed25519-signed snapshot of finalized SPL balances, Poseidon Merkle tree (depth 20) |
| Wallet ownership | Ed25519 signMessage verification (tweetnacl) at registration |
| Replay protection | Verifier-issued single-use challenges bound into the proof + expiry + app-scoped nullifiers |
| Wallets | Solana-native wallets only (Phantom, Solflare incl. web wallet, Backpack, Glow) via Solana Wallet Adapter; Wallet-Standard EVM/multichain wallets such as MetaMask are hidden and auto-disconnected (app/src/components/wallet-button.tsx) |
Nothing is mocked: every “valid” in the UI is a pairing check performed by snarkjs plus an Ed25519 signature check. The only test double in the whole repository is an in-memory stand-in for Solana RPC in unit tests, plus one opt-in test that hits live devnet.
What a proof means
A valid GHOST proof establishes:
- Some identity registered in the GHOST registry, whose wallet's finalized balance of mint
Mat the snapshot slot range was ≥ threshold, - is controlled by whoever generated this proof (knowledge of the identity secret and wallet key),
- for this app (
appId), this challenge, before this expiry.
It is a statement about historical state — the snapshot's slot range — not a live balance. The bundle carries createdAt, baseSlot, slotMin and slotMax; verifiers decide how old a snapshot they accept (maxSnapshotAgeSeconds).
What a proof does not mean
- It does not prove the user still holds the tokens now.
- It does not prove anything without trusting the snapshot attester (see Architecture).
- It does not guarantee anonymity. See Threat model.
Where to go next
- Architecture — components, data flow, trust model, design rationale
- Threat model — attacks, mitigations and every known privacy limitation
- Circuit specification — exact constraints and public signals
- Developer SDK — integrate GHOST verification in your app
- HTTP API
- Setup & deployment