Standard Phantom Keys
Standard Phantom Keys are one-time bearer instruments backed by the CommitRevealVault (for GHOST tokens and other fungible assets) or the OpenGhostVault (for arbitrary data). When the key is used to reveal, the commitment's nullifier is spent on-chain and the key is permanently consumed. The lifecycle is: generate, commit, share, reveal, done.
Lifecycle
Step-by-Step
Step 1: Generate Secrets
The sender generates a 128-bit random seed and derives all cryptographic secrets using HKDF-SHA256:
| Derived Value | HKDF Info String | Purpose |
|---|---|---|
secret | ghostcoin-secret-v1 | Primary secret in commitment preimage |
nullifierSecret | ghostcoin-nullifier-v1 | Used for nullifier derivation |
blinding | ghostcoin-blinding-v1 | Randomizes the commitment (hiding property) |
changeBlinding | ghostcoin-change-blinding-v1 | Used if recipient does a partial withdrawal |
All values are reduced modulo the BN254 scalar field prime to produce valid field elements.
Step 2: Vanish (Commit to Tree)
The sender computes the commitment and submits it to the CommitRevealVault:
For a standard key with no policy, policyId = 0 and policyParamsHash = 0.
The contract:
- Burns the deposited tokens (removes them from the sender's balance).
- Inserts the commitment as a new leaf in the Merkle tree.
- Returns the
leafIndex(the commitment's position in the tree).
After this transaction, the tokens exist only as a hash in the tree. There is no on-chain record linking the commitment to the sender's address, the amount, or the token type.
Step 3: Encode the Phantom Key
The sender encodes the seed, amount, and leaf index into a numeric string:
[version][seed digits][significand length][significand][exponent][index length][leaf index][checksum]
The amount is stored in scientific notation (significand and exponent) to save digits. The leaf index uses variable-length encoding to avoid wasting digits on leading zeros. A 4-digit checksum provides error detection.
The result is displayed in groups of four digits for readability:
9473 0018 7376 9372 0484 1273
Step 4: Share the Key
The Phantom Key can be shared through any channel:
| Channel | Properties |
|---|---|
| Printed card | Physical bearer instrument. No digital trail. |
| Spoken aloud | Ephemeral transfer. Groups of four digits are easy to dictate. |
| Encrypted message | Digital transfer with forward secrecy (Signal, etc.) |
| QR code | Scan to redeem. Convenient for point-of-sale or gift cards. |
| Written on paper | Low-tech, high-security for cold storage. |
The key contains everything needed to reveal the commitment. No additional context, no account credentials, no network state is required (beyond access to the Specter chain to submit the proof).
Step 5: Reveal (Redeem)
The recipient decodes the Phantom Key, re-derives the secrets from the seed, fetches the current Merkle proof from the chain, and generates a Groth16 proof using the Redemption Circuit.
The proof demonstrates (without revealing any private inputs):
- The recipient knows the preimage of a commitment in the tree.
- The nullifier is correctly derived from that commitment.
- The withdrawal amount does not exceed the original deposit.
- The proof is bound to the recipient's address (preventing front-running).
The on-chain verifier:
- Checks the proof against the verification key.
- Verifies the Merkle root is a known historical root.
- Records the nullifier to prevent double-spending.
- Mints fresh tokens to the recipient's address.
The key is now consumed. The nullifier is permanently recorded. Attempting to use the same key again will fail because the nullifier has already been spent.
Partial Withdrawals
A Phantom Key holder can withdraw less than the full amount. The Redemption Circuit handles this via a change commitment:
The change commitment uses the same secret and nullifierSecret (derived from the original seed) but a different blinding factor (changeBlinding, also derived from the seed via a different HKDF info string). This means the change Phantom Key (V3 format) can be derived from the original seed — the holder does not need to generate a new seed for the change.
Token-Backed vs. Data-Backed Keys
Standard Phantom Keys can be backed by either tokens or data, depending on which vault they commit to:
| Property | Token-Backed (CommitRevealVault) | Data-Backed (OpenGhostVault) |
|---|---|---|
| Commitment structure | 7-input Poseidon (includes tokenId, amount) | 4-input Poseidon (includes dataHash) |
| Deposit | Burn tokens into vault | Pay commitment fee |
| Reveal | Mint tokens to recipient | Return sealed data |
| Partial withdrawal | Yes (change commitment) | No (data is atomic) |
| Circuit | Redemption (8 public inputs) | Redemption variant for Open Ghost |
Use Cases
| Use Case | Description |
|---|---|
| Private transfers | Send GHOST tokens without linking sender and recipient on-chain. |
| Gift cards | Print Phantom Keys on physical cards. Redeemable by anyone. |
| Offline redemption | Keys work without internet until the reveal step. Useful for in-person transactions. |
| One-time credential sharing | Commit a credential hash, share the key, recipient reveals and verifies. |
| Escrow without intermediary | Commit tokens, share the key with conditions. The key itself is the escrow. |
| Cross-border value transfer | A number that carries value. No bank, no intermediary, no ID. |
Security Properties
| Property | Guarantee |
|---|---|
| Bearer semantics | Whoever knows the numbers controls the commitment. |
| Unlinkability | The reveal transaction cannot be linked to the commit transaction by any on-chain observer. |
| Front-running resistance | The proof binds to the recipient's address. A miner/validator who sees the proof in the mempool cannot redirect the tokens. |
| Double-spend prevention | The nullifier is deterministically derived and recorded on-chain. A second reveal with the same key fails. |
| Amount privacy | The on-chain reveal shows only the withdrawal amount, not the original deposit amount (in partial withdrawal cases, the change is re-committed privately). |