Lifecycle Mental Model
This section explains what the protocol does and where data lives. Understanding this is essential before building.
What the Protocol Does
Ghost Protocol is a general-purpose ZK-SNARK commit-reveal mechanism that enables anonymous, untraceable data commitments. Users commit data cryptographically and later reveal it with a ZK proof—without exposing the link between commit and reveal.
The protocol uses a commit-reveal mechanism:
- Commit: Record a cryptographic commitment on-chain
- Reveal: Prove knowledge of secrets with a ZK proof and execute application logic
Between commit and reveal, the commitment exists on-chain but its contents are hidden. Applications can implement any logic in their callbacks—token transfers, access grants, voting, or any other action. After reveal, the commitment can never be used again.
Token Privacy (Vanish/Summon)
One common use case built on Ghost Protocol is token privacy:
- Vanish: Burn GHOST tokens in
onCommit, creating a commitment - Summon: Mint GHOST tokens in
onRevealto any recipient
This breaks the on-chain link between sender and receiver. But remember: Vanish/Summon is just one application—the core protocol works with any data.
Data Lifecycle
┌─────────────────────────────────────────────────────────────────────────────┐
│ COMMIT PHASE │
│ │
│ OFF-CHAIN (your responsibility): │
│ ├─ Generate: secret, nullifierSecret, blinding (random 32-byte values) │
│ ├─ Compute: dataHash = hash(your application data) │
│ ├─ Compute: commitment = Poseidon(Poseidon(secret, nullifierSecret), │
│ │ Poseidon(dataHash, blinding)) │
│ └─ STORE THESE VALUES. If lost, your commitment is unrecoverable. │
│ │
│ ON-CHAIN (permanent): │
│ └─ commitment is added to Merkle tree at leafIndex │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ WAITING PHASE │
│ │
│ The commitment exists on-chain. │
│ No one can determine what was committed without the off-chain secrets. │
│ The Merkle root is updated periodically by the relayer. │
│ Your commitment becomes provable once included in a known root. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ REVEAL PHASE │
│ │
│ OFF-CHAIN (your responsibility): │
│ ├─ Compute: nullifier = Poseidon(Poseidon(nullifierSecret, commitment), │
│ │ leafIndex) │
│ ├─ Generate: ZK proof proving you know the secret for this commitment │
│ └─ The proof ties together: root, nullifier, dataHash, recipient │
│ │
│ ON-CHAIN (permanent): │
│ ├─ Proof is verified │
│ ├─ Nullifier is marked as SPENT (forever) │
│ └─ Application callback executes (if any) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ TERMINAL STATE │
│ │
│ The nullifier is spent. The commitment can never be revealed again. │
│ The off-chain secrets are now useless. You can delete them. │
│ │
│ If you never revealed: the commitment exists forever, unrevealed. │
│ If you lost your secrets before revealing: the commitment is dead forever. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
What Exists Where
| Data | Location | Lifetime | Who Controls It |
|---|---|---|---|
secret | Off-chain only | Until reveal (then delete) | You |
nullifierSecret | Off-chain only | Until reveal (then delete) | You |
blinding | Off-chain only | Until reveal (then delete) | You |
dataHash | Off-chain AND in proof | Permanent | Derived from app data |
commitment | On-chain (Merkle tree) | Permanent | Protocol |
leafIndex | On-chain (from event) | Permanent | Protocol |
root | On-chain (100 most recent) | Rolling window | Relayer updates |
nullifier | On-chain after reveal | Permanent once spent | Protocol |
proof | Submitted at reveal | Verified then discarded | You generate |
What Happens If...
| Scenario | Outcome |
|---|---|
You lose secret before reveal | Permanent loss. Commitment can never be revealed. |
You lose nullifierSecret before reveal | Permanent loss. Cannot compute nullifier. |
You lose leafIndex | Recoverable. Query events or tree to find it. |
| Root becomes stale (>100 roots ago) | Reveal fails. Wait for new root, regenerate proof. |
| You try to reveal twice | Second reveal fails. Nullifier already spent. |
Your app reverts in onReveal | Reveal transaction reverts. Nullifier NOT spent. |
If you lose secret or nullifierSecret before reveal, your commitment is unrecoverable. There is no recovery mechanism. Store these values securely.
Next Steps
- Terminology - Learn the canonical terms
- One-Time Access Token Tutorial - Build your first application