Skip to main content

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 ValueHKDF Info StringPurpose
secretghostcoin-secret-v1Primary secret in commitment preimage
nullifierSecretghostcoin-nullifier-v1Used for nullifier derivation
blindingghostcoin-blinding-v1Randomizes the commitment (hiding property)
changeBlindingghostcoin-change-blinding-v1Used 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:

commitment=Poseidon7(secret,  nullifierSecret,  tokenId,  amount,  blinding,  policyId,  policyParamsHash)\text{commitment} = \text{Poseidon}_7(\text{secret},\; \text{nullifierSecret},\; \text{tokenId},\; \text{amount},\; \text{blinding},\; \text{policyId},\; \text{policyParamsHash})

For a standard key with no policy, policyId = 0 and policyParamsHash = 0.

The contract:

  1. Burns the deposited tokens (removes them from the sender's balance).
  2. Inserts the commitment as a new leaf in the Merkle tree.
  3. 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:

ChannelProperties
Printed cardPhysical bearer instrument. No digital trail.
Spoken aloudEphemeral transfer. Groups of four digits are easy to dictate.
Encrypted messageDigital transfer with forward secrecy (Signal, etc.)
QR codeScan to redeem. Convenient for point-of-sale or gift cards.
Written on paperLow-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:

  1. Checks the proof against the verification key.
  2. Verifies the Merkle root is a known historical root.
  3. Records the nullifier to prevent double-spending.
  4. 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:

PropertyToken-Backed (CommitRevealVault)Data-Backed (OpenGhostVault)
Commitment structure7-input Poseidon (includes tokenId, amount)4-input Poseidon (includes dataHash)
DepositBurn tokens into vaultPay commitment fee
RevealMint tokens to recipientReturn sealed data
Partial withdrawalYes (change commitment)No (data is atomic)
CircuitRedemption (8 public inputs)Redemption variant for Open Ghost

Use Cases

Use CaseDescription
Private transfersSend GHOST tokens without linking sender and recipient on-chain.
Gift cardsPrint Phantom Keys on physical cards. Redeemable by anyone.
Offline redemptionKeys work without internet until the reveal step. Useful for in-person transactions.
One-time credential sharingCommit a credential hash, share the key, recipient reveals and verifies.
Escrow without intermediaryCommit tokens, share the key with conditions. The key itself is the escrow.
Cross-border value transferA number that carries value. No bank, no intermediary, no ID.

Security Properties

PropertyGuarantee
Bearer semanticsWhoever knows the numbers controls the commitment.
UnlinkabilityThe reveal transaction cannot be linked to the commit transaction by any on-chain observer.
Front-running resistanceThe proof binds to the recipient's address. A miner/validator who sees the proof in the mempool cannot redirect the tokens.
Double-spend preventionThe nullifier is deterministically derived and recorded on-chain. A second reveal with the same key fails.
Amount privacyThe on-chain reveal shows only the withdrawal amount, not the original deposit amount (in partial withdrawal cases, the change is re-committed privately).