Ghost Protocol
The Ghost Protocol is Specter's core privacy primitive — a commit-reveal system that uses zero-knowledge proofs to break the link between depositing and withdrawing value.
How it works
The key insight
Tokens are not transferred or escrowed — they are destroyed on commit and created fresh on reveal. There is no pool, no escrow contract, and no link between the two operations. The only thing connecting them is a zero-knowledge proof that says "I know the preimage of some commitment in the tree."
The flow in detail
Step 1: Commit (burn)
The user calls commit() or commitNative() on the CommitRevealVault. The vault:
- Burns the tokens via the Ghostmint precompile (
BankKeeper.BurnCoins()) - Computes a Poseidon hash commitment from the user's secret inputs
- Inserts the commitment into the Merkle tree
- Emits a
Committedevent
Step 2: Root update
The root updater relayer service watches for CommitmentAdded events, rebuilds the off-chain Merkle tree, and submits the new root on-chain. This takes 5–15 seconds.
Step 3: Reveal (mint)
The user generates a Groth16 ZK proof proving they know the preimage of some commitment in the tree — without revealing which one. The vault:
- Verifies the proof against the on-chain verifier
- Checks the nullifier hasn't been spent (prevents double-reveal)
- Registers the nullifier
- Mints fresh tokens via the Ghostmint precompile (
BankKeeper.MintCoins())
Privacy properties
| Property | How it's achieved |
|---|---|
| Sender privacy | Tokens are burned, not sent. No outgoing transfer to trace. |
| Receiver privacy | Tokens are minted fresh. No incoming transfer to trace. |
| Amount privacy | Partial reveals with change commitments obscure amounts. |
| Unlinkability | The ZK proof proves membership in the full tree without revealing which leaf. The anonymity set is all commitments in the tree. |
| Double-spend prevention | Nullifiers derived from user secrets are registered on-chain. Same commitment cannot be revealed twice. |
What can you commit?
The Ghost Protocol is data-agnostic. The commitment structure stores:
- secret — user's private key for this commitment
- nullifierSecret — used to derive the unique nullifier
- amount — the value being committed
- tokenId — hash identifying the token type
- blinding — random blinding factor
- policyId — optional policy contract address
- policyParamsHash — optional policy parameters
Any data that fits this structure can be committed. Native GHOST, GhostERC20 tokens, and arbitrary data types all use the same circuit.
Next steps
- Commit Flow — detailed commit process with code
- Reveal Flow — proof generation and reveal
- Commitment Structure — Poseidon hash fields
- Integration Guide — end-to-end tutorial