Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Airdrop Proofs

Our tool produces one ZK proof per eligible shielded note:

  • Sapling (Groth16 / bellman; adapted from Sapling Spend)
  • Orchard (Halo2; adapted from Orchard Action):

These are not Zcash spend proofs. They prove note ownership and snapshot eligibility without authorizing a transaction, and expose an airdrop-scoped nullifier for double-claim prevention.

What the ZK proof establishes (high level)

In-circuit (pool-specific details in sub-sections):

  • Ownership/spend consistency (recipient binding + public rk)
  • Snapshot inclusion (note membership of the note commitment root)
  • Snapshot unspentness (gap-tree non-membership against the spent-nullifier gap-root)
  • Airdrop nullifier derivation (public, domain-separated from Zcash nullifier)
  • Value binding via cv (native) or cv_sha256 (custom SHA-256 scheme)

Outside the circuit:

  • A spend-authorizing signature under rk binds the proof to an external message/context.

Crate layout

Each pool has two crates and one or more patched upstream dependencies:

SaplingOrchard
Circuitzair-sapling-circuitzair-orchard-circuit
Prover / verifierzair-sapling-proofszair-orchard-proofs
Patched depssapling-cryptoorchard, halo2-gadgets

The patches expose internal APIs (nullifier derivation with configurable domain, Pedersen/Sinsemilla hash internals, key types) so that host-side code can compute the same airdrop nullifiers and commitments that the circuits enforce. See the per-pool pages for details.

Key differences from standard Zcash spend circuits

Both circuits are closely aligned with the Sapling Spend Circuit and the Orchard Spend Action and reuse their note-integrity and ownership checks (recipient binding, rk derivation, note commitment, Merkle membership). The ZAIR-specific additions are:

Airdrop nullifier. The circuit computes two nullifiers from the same preimage: the standard Zcash nullifier (kept private) and an airdrop nullifier under a domain-separated derivation (exposed as a public input). Sapling uses BLAKE2s with a different personalization (b"ZAIRTEST"); Orchard uses a different hash-to-curve basepoint derived from a target_id string.

Gap-tree non-membership. Instead of exposing the real nullifier for double-spend prevention, the circuit proves that the private nullifier falls inside a gap in the sorted spent-nullifier set. The prover witnesses adjacent bounds (left < nf < right) and a Merkle path to the gap-tree root. Leaf hashing uses level 62 for domain separation from internal note-tree levels.

Unconditional note-anchor binding (Sapling). Upstream Sapling Spend skips anchor enforcement for zero-value dummy spends. ZAIR always enforces the note commitment root, so even zero-valued notes are bound to the snapshot.

SHA-256 value commitment (optional). When the sha256 scheme is selected, the circuit computes SHA256(b"Zair" || LE64(value) || rcv_sha256) and exposes the digest as public input instead of the native Pedersen commitment point. Orchard's SHA-256 mode uses the Table16 gadget from patched halo2-gadgets and requires K=17 (vs K=12 for native, and K=11 for standard spend).