privacy-patterns

SKILL.md

Privacy Patterns for Midnight

Design and implement privacy-preserving applications using zero-knowledge proofs.

Core Privacy Model

Concept Description Visibility
Public Ledger state Everyone
Private Circuit inputs Only prover
Witness Prover-provided data Only prover
Disclosed Explicitly revealed Everyone

Reference Files

Topic Resource
Zero-Knowledge Basics references/zk-fundamentals.md
Commitment Schemes references/commitments.md
Nullifier Patterns references/nullifiers.md
Selective Disclosure references/selective-disclosure.md

Pattern Overview

1. Commitment Scheme

Hide a value while binding to it:

commitment = persistentCommit(value, randomness);
// Later: prove you know the opening

2. Nullifier Pattern

Prevent double-use without revealing identity:

nullifier = transientHash(secret, commitment);
// Can only be generated once per commitment

3. Selective Disclosure

Prove properties without revealing data:

// Prove over 18 without revealing actual age
disclose(age >= 18);  // Only boolean is public

4. Merkle Membership

Prove membership in a set without revealing position:

// Verify path from leaf to root
assert verifyMerklePath(leaf, proof, root);

Quick Examples

Private Balance Check

// Only reveal if balance is sufficient, not actual amount
export circuit checkFunds(balance: Uint<64>, required: Uint<64>): Boolean {
  return disclose(balance >= required);
}

Anonymous Voting

export circuit vote(voter: Bytes<32>, choice: Boolean): [] {
  // Voter identity disclosed (prevents double voting)
  hasVoted.insert(voter);
  // Choice remains private, only totals change
  if (choice) { yesCount = yesCount + 1; }
}

Commitment-Reveal

witness randomness: Field;

// Phase 1: Commit
export circuit commit(value: Uint<64>): Field {
  return persistentCommit(value, randomness);
}

// Phase 2: Reveal
export circuit reveal(value: Uint<64>, commitment: Field): [] {
  assert persistentCommit(value, randomness) == commitment;
  disclose(value);
}

Privacy Best Practices

  • ✅ Use witness for data that should never appear on-chain
  • ✅ Use persistentCommit (with randomness) to hide values
  • ✅ Use nullifiers to prevent double-actions
  • ✅ Disclose only what's necessary (prefer booleans)
  • ❌ Don't store unhashed sensitive data on ledger
  • ❌ Don't use predictable randomness in commitments
  • ❌ Don't reveal intermediate values unnecessarily

Privacy Levels

┌────────────────────────────────────────────────┐
│ Level 0: Fully Public                          │
│ - All data visible on-chain                    │
├────────────────────────────────────────────────┤
│ Level 1: Hidden Values                         │
│ - Commitments on-chain, values private         │
├────────────────────────────────────────────────┤
│ Level 2: Unlinkable Actions                    │
│ - Nullifiers prevent linking actions           │
├────────────────────────────────────────────────┤
│ Level 3: Anonymous Membership                  │
│ - Merkle proofs hide set position              │
└────────────────────────────────────────────────┘

When to Use Each Pattern

Pattern Use Case
Commitment Sealed bids, hidden votes before reveal
Nullifier Preventing double-spend, one-time tokens
Merkle Proof Membership in allowlist without revealing identity
Selective Disclosure Age verification, credential proofs

Resources

Weekly Installs
3
First Seen
Jan 31, 2026
Installed on
gemini-cli3
opencode2
replit2
antigravity2
claude-code2
github-copilot2