Skip to main content

Data Types and Commitment Variants

The Ghost Protocol supports multiple commitment structures, each optimized for a different class of data. All variants share the same underlying Poseidon hash function and the same Merkle tree infrastructure. They differ in the number and semantics of their inputs, which determines what properties the ZK proof can attest to.

This page describes the three commitment variants — Open Ghost, Token, and Access Proof — and shows how different real-world data types map to them.

Commitment Variant 1: Open Ghost (4-Input)

The Open Ghost commitment is the general-purpose variant. It commits to an arbitrary data hash with no assumptions about the data's structure or semantics.

commitment=Poseidon4(secret,  nullifierSecret,  dataHash,  blinding)\text{commitment} = \text{Poseidon}_4(\text{secret},\; \text{nullifierSecret},\; \text{dataHash},\; \text{blinding})
InputDescription
secretRandom value known only to the committer. Required for proof generation.
nullifierSecretRandom value used to derive the nullifier. Separate from secret to allow delegation of reveal rights without compromising the secret.
dataHashPoseidon(data) — the hash of the actual payload. Can be the hash of a credential, an image, an API key, an encryption key, or any other data.
blindingRandom blinding factor that ensures two commitments to the same data produce different commitment values. Prevents deduplication attacks.

The dataHash field is the protocol's point of extensibility. Because dataHash is simply the Poseidon hash of arbitrary data, the Open Ghost commitment can encode anything. The protocol does not interpret dataHash — it only verifies that the prover knows a preimage of the commitment that includes this hash.

Reveal Public Inputs

When an Open Ghost commitment is revealed, the ZK proof exposes:

Public InputPurpose
rootThe Merkle tree root at the time of proof generation. Verifier checks this is a recognized root.
nullifierHashPoseidon(nullifierSecret, leafIndex) — recorded on-chain to prevent double-reveal.
dataHashThe hash of the underlying data. Allows the verifier or receiving contract to act on the data type without seeing the plaintext.
accessTagAn optional tag binding the proof to a specific context (session, contract, purpose). Prevents proof reuse across contexts.

Commitment Variant 2: Token (7-Input)

The Token commitment extends the Open Ghost structure with fields specific to fungible and non-fungible token operations. It encodes the token identity, amount, and policy bindings directly in the commitment.

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})
InputDescription
secretRandom value known only to the committer.
nullifierSecretRandom value for nullifier derivation.
tokenIdIdentifier for the token type (e.g., GHOST native token, an ERC-20 equivalent, or an NFT identifier).
amountThe quantity of tokens committed. Encoded as a field element. For NFTs, this is 1.
blindingRandom blinding factor.
policyIdIdentifier for the policy bound to this commitment (e.g., timelock, destination restriction). Zero if no policy.
policyParamsHashPoseidon(policyParams) — hash of the policy parameters. Allows the circuit to verify policy compliance without revealing the full policy.

The additional inputs allow the ZK circuit to verify token-specific properties:

  • The amount revealed matches the amount committed (no inflation)
  • The token ID matches (no type substitution)
  • The policy conditions are satisfied (timelock has elapsed, destination is approved, threshold is met)

Reveal Public Inputs

Public InputPurpose
rootRecognized Merkle root.
nullifierHashPrevents double-spending.
recipientThe address that will receive the minted tokens.
amountThe token quantity to mint. Verified in-circuit to match the committed amount.

Commitment Variant 3: Access Proof (4 Public Inputs)

The Access Proof variant is designed for non-consumptive data access — proving knowledge of committed data without spending the commitment. Unlike the Open Ghost and Token variants, an Access Proof does not record a nullifier. The commitment remains in the Merkle tree and can be proven against repeatedly.

This variant is used for persistent credentials, ongoing access rights, and any scenario where the user needs to prove the same fact multiple times.

Public Inputs

Public InputPurpose
rootRecognized Merkle root.
dataHashThe data hash being proven. Allows the verifier to check what type of data the prover claims to hold.
sessionNonceA nonce binding the proof to a specific session or time window. Prevents proof replay across sessions while allowing repeated use within a session.
accessTagA tag binding the proof to a specific verifier, contract, or purpose. Prevents a proof generated for one context from being used in another.

Differences from Consumptive Reveals

PropertyOpen Ghost / Token (Consumptive)Access Proof (Non-Consumptive)
Nullifier recordedYes — commitment can only be revealed onceNo — commitment can be proven repeatedly
Commitment consumedYes — after reveal, the commitment is "spent"No — commitment remains active in the tree
Use caseOne-time redemption (tokens, bearer instruments)Ongoing access (credentials, subscriptions, identity)
Replay protectionNullifier registrySession nonce + access tag
Supply effect (tokens)Burns on commit, mints on revealNo supply effect — proof only

Data Type Mapping

The following table shows how different real-world data types map to the commitment variants, circuits, and retrieval modes.

Data TypeCommitment VariantCommitment InputsVaultCircuitRetrieval Mode
CredentialsOpen Ghost (4-input)secret, nullifierSecret, Poseidon(credential), blindingGeneral Merkle treeOpen Ghost circuit or Access Proof circuitAccess Proof (non-consumptive) — prove credential repeatedly
ImagesOpen Ghost (4-input)secret, nullifierSecret, Poseidon(imageHash), blindingGeneral Merkle treeOpen Ghost circuitConsumptive (provenance claim) or Access Proof (ongoing proof)
API KeysOpen Ghost (4-input)secret, nullifierSecret, Poseidon(apiKey), blindingGeneral Merkle treeOpen Ghost circuitConsumptive — key rotation spends old commitment, creates new
Encryption KeysOpen Ghost (4-input)secret, nullifierSecret, Poseidon(pubKey), blindingGeneral Merkle treeAccess Proof circuitAccess Proof — prove key ownership without revealing key
Tokens (GHOST)Token (7-input)secret, nullifierSecret, tokenId, amount, blinding, policyId, policyParamsHashToken Merkle treeToken redemption circuitConsumptive — burn on Vanish, mint on Summon
Bearer InstrumentsOpen Ghost (4-input)secret, nullifierSecret, Poseidon(instrument), blindingGeneral Merkle treeOpen Ghost circuitConsumptive — single-use redemption via nullifier

Vault Separation

The protocol maintains separate Merkle trees (vaults) for different commitment types:

  • General Merkle tree: Stores Open Ghost commitments for all non-token data types. Shared across credentials, images, keys, and other generic data.
  • Token Merkle tree: Stores Token commitments. Separated to allow independent scaling and to isolate the token supply accounting from general data operations.

Both trees use the same depth (20 levels, supporting approximately 1 million entries each), the same Poseidon hash function, and the same proof verification infrastructure. The separation is a logical choice for operational clarity, not a cryptographic necessity.

Extensibility

Adding support for a new data type requires:

  1. Define the data hash computation: Specify how the new data type is hashed into a dataHash field element. For simple data, this is Poseidon(data). For structured data, it may be Poseidon(field1, field2, ..., fieldN).
  2. Choose a commitment variant: Open Ghost (4-input) for most data types. Token (7-input) only if the data has an amount, identity, and policy binding.
  3. Choose a retrieval mode: Consumptive (one-time reveal with nullifier) or non-consumptive (repeated access proofs with session nonces).
  4. Implement application logic: Write the smart contract or module that interprets the revealed dataHash and takes the appropriate action.

No changes to the ZK circuits are required for new data types that fit within existing commitment structures. The Poseidon hash accepts arbitrary field elements, and the Merkle tree stores arbitrary commitments. The protocol is extensible at the application layer without modifying the cryptographic layer.

Example: Adding a New Data Type

Suppose an application wants to commit signed documents to the Ghost Protocol.

  1. Data hash: dataHash = Poseidon(documentHash, signerPubKeyHash, timestamp)
  2. Commitment variant: Open Ghost (4-input)
  3. Retrieval mode: Access Proof (non-consumptive) — the signer wants to prove the document exists and was signed by them, repeatedly, without consuming the commitment.
  4. Application logic: A verifier contract checks the revealed dataHash against a registry of accepted document formats and signer public keys.

The ZK circuit does not change. The Merkle tree does not change. Only the application-layer interpretation of dataHash is new. This is the power of a data-agnostic commitment protocol.