Skip to main content

5.1 Commitment Construction

In Abyss, deposits are not tracked as balances tied to addresses. Instead, each deposit is represented as a cryptographic commitment derived from a secret known only to the depositor. This commitment is what enters the anonymity pool. Formally, a commitment is constructed as:
commitment C := H(secret_key || deposit_nonce || deposit_amount)
Where:
  • secret_key is generated client-side and never revealed
  • deposit_nonce ensures uniqueness across deposits
  • deposit_amount binds value to the commitment
The hash function H is collision-resistant and circuit-compatible. Once computed, C is inserted as a leaf into the global Merkle tree representing the anonymity pool. This design ensures that the protocol can verify the existence of a deposit without learning anything about who made it or how it will be spent.

5.2 Merkle-Based Anonymity Set

All commitments exist within a single Merkle tree:
AnonymitySet := { C₁, C₂, …, Cₙ }
The anonymity set size |AnonymitySet| = n directly bounds privacy. A withdrawal proof only asserts that one of these commitments is being spent, without revealing which one. Key property:
Pr(link deposit → withdrawal) ≈ 1 / n
assuming uniform usage and no external leakage. Abyss intentionally avoids multiple pools or denominations to prevent entropy fragmentation. Every new deposit strictly increases the anonymity set for all participants.

5.3 Nullifier Design

To prevent double-spending without revealing identity, Abyss uses nullifiers. For a given secret:
nullifier N := H(secret_key || withdrawal_index)
Properties:
  • Deterministic per withdrawal
  • Unique per spend
  • Unlinkable to commitment without secret knowledge
On withdrawal, N is revealed as a public input and checked against an on-chain nullifier registry:
require(!nullifierUsed[N], "DOUBLE_SPEND");
nullifierUsed[N] = true;
This ensures that no withdrawal can be repeated, while revealing nothing about which commitment generated it.

5.4 Infinite Withdrawal Model

Unlike single-use note systems, Abyss supports multiple withdrawals from a single deposit. Internally, this is enforced through balance accounting inside the ZK circuit. The circuit asserts:
Σ withdrawn_amounts ≤ deposit_amount
Each withdrawal consumes balance but does not exhaust the commitment unless fully spent. This enables:
  • Micropayments
  • Streaming payouts
  • Merchant payments
  • Partial liquidity exits
All without reducing anonymity.

5.5 Anonymity Set Dynamics

Anonymity is not static. It evolves with protocol usage. Positive factors:
  • Frequent deposits
  • Overlapping withdrawals
  • Time separation between actions
Negative factors:
  • Immediate withdraw-after-deposit
  • Unique withdrawal patterns
  • Low pool usage
Abyss does not enforce behavior. It provides the cryptographic substrate. Privacy emerges from correct usage patterns, not protocol coercion.

5.6 Security Implications

Commitments, nullifiers, and Merkle inclusion together ensure:
  • Ownership without identity
  • One-time spend guarantees
  • No balance inflation
  • No linkage across time
These primitives are the foundation upon which all higher-level privacy features in Abyss are built.