CA
GHOST

Zero-knowledge wallet identity · Solana

GHOST

Your assets. Your identity. Your privacy.

“Prove what you own without revealing who you are.”

One wallet, many unlinkable identities. Show that you hold at least N of an SPL token without showing your address, your balance, or your other holdings — using real Groth16 proofs over an attested Solana snapshot.

identity = Poseidon(1, secret) live

    Computed in your browser with the circuit's Poseidon parameters, shown in base58 like Solana keys. These are commitments, not wallet addresses — that's the point: none of them can be traced to a wallet. Demo secrets are random and discarded.

    A verifier learns

    • ✓Some GHOST identity held ≥ the threshold of this mint at the snapshot slot
    • ✓Which signed snapshot was used, and roughly how many identities could have produced the proof
    • ✓A nullifier unique to their app — used to stop double claims
    • ✓That the proof answers their own fresh, unexpired challenge

    A verifier never receives

    • ✕Your wallet address or any signature from it
    • ✕Your exact balance or your other token holdings
    • ✕Your identity commitment or position in the tree
    • ✕Anything that links you across different apps

    Protocol

    Four steps. One circuit.

    01

    Create a ghost

    Generate a random identity secret in your browser. Only its Poseidon commitment is registered, with a wallet signature proving you own the wallet.

    02

    Snapshot

    At a finalized Solana slot, the attester reads SPL balances over RPC and commits every (identity, mint, balance) into a Merkle tree, then signs the root.

    03

    Prove

    Your browser generates a Groth16 proof: “some leaf in this signed tree is mine and its balance ≥ threshold”. The secret never leaves your device.

    04

    Verify

    Any app checks the pairing equation, the attester signature, expiry, a single-use challenge and an app-scoped nullifier. No wallet address involved.

    Snapshot, not live

    Proofs establish your balance at the snapshot's finalized slot range — historical, not current. Every proof carries the slot and time; verifiers choose how old is acceptable.

    Explicit trust

    Solana offers no light-client state proofs a circuit can check, so balances are attested by a snapshot signer. A dishonest attester could include false balances; it cannot forge proofs or deanonymise nullifiers.

    Privacy has limits

    Small anonymity sets, timing, IP addresses and RPC logs can all correlate activity. GHOST reduces what is revealed; it does not guarantee anonymity. Threat model →

    Developers

    Gate anything on private holdings.

    The TypeScript SDK issues requests with single-use challenges, opens GHOST for the user, and verifies the returned proof server-side with replay and sybil protection.

    SDK reference →
    import { GhostVerifier } from "@ghost/sdk/verifier";
    
    const verifier = new GhostVerifier({
      appId: "https://dao.example/vote-7",
      verificationKey,
      trustedAttesters: [GHOST_ATTESTER],
    });
    
    // 1. server: issue a request
    const request = await verifier.createRequest({
      mint: JUP_MINT,
      minBalance: 1_000_000_000n,   // raw units
      nullifierMode: "wallet",       // one per wallet
    });
    
    // 2. browser: requestGhostProof(request, …)
    // 3. server:
    const { valid, statement } = await verifier.verify(bundle);