Canonical Terminology
Every term has exactly one meaning. Use these definitions.
Core Values
| Term | Type | Definition | Computed How |
|---|---|---|---|
secret | bytes32 | Random value known only to committer. Proves ownership of commitment. | crypto.getRandomValues() → 32 bytes |
nullifierSecret | bytes32 | Random value used to derive nullifier. Separate from secret for privacy. | crypto.getRandomValues() → 32 bytes |
blinding | bytes32 | Random value that blinds the dataHash in the commitment. | crypto.getRandomValues() → 32 bytes |
dataHash | bytes32 | Hash of application-specific data. Ties commitment to its purpose. | Poseidon(app_field_1, app_field_2) or keccak256(data) % FIELD_SIZE |
commitment | bytes32 | The on-chain identifier. Hides all inputs. Cannot be reversed. | See formula below |
leafIndex | uint256 | Position in Merkle tree. Assigned at commit time. | Returned from commit() / emitted in event |
nullifier | bytes32 | Unique spend tag. Derived from nullifierSecret + leafIndex. | See formula below |
root | bytes32 | Merkle root at a point in time. Must be in last 100 roots. | Computed by relayer, stored on-chain |
proof | Proof struct | Groth16 ZK proof. Proves knowledge of secrets without revealing them. | Generated off-chain |
Field Size Constraint
All values passed to Poseidon or used in proofs must be valid BN254 field elements:
FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617
If a value ≥ FIELD_SIZE, the commitment or proof is invalid.
Collision Safety: Commitment collisions are cryptographically infeasible assuming Poseidon preimage resistance and correct field handling. You do not need to check for collisions.
Commitment Formula (Exact)
commitment = Poseidon(
Poseidon(secret, nullifierSecret),
Poseidon(dataHash, blinding)
)
This is a 2-level tree of Poseidon T3 (2-input) hashes. The order matters. Swapping inputs produces a different commitment.
Nullifier Formula (Exact)
intermediate = Poseidon(nullifierSecret, commitment)
nullifier = Poseidon(intermediate, leafIndex)
The nullifier depends on leafIndex, which is only known after commit. You cannot precompute the nullifier before committing.
Core Protocol Operations
| Term | Meaning |
|---|---|
| Commit | Add a commitment to the Merkle tree (core protocol) |
| Reveal | Prove knowledge of secrets with ZK proof and mark nullifier as spent (core protocol) |
Token Privacy Operations (Application Layer)
| Term | Meaning |
|---|---|
| Vanish | Burn GHOST tokens and create a commitment (uses Commit internally) |
| Summon | Prove ownership and mint GHOST tokens to recipient (uses Reveal internally) |
Vanish/Summon are built on top of Commit/Reveal. The core protocol is data-agnostic—it can be used for tokens, access control, voting, or any private data.
Next Steps
- Lifecycle Mental Model - Understand the full data flow
- Safety Rules - Rules for building applications