Inspiration

Every deal starts with a signal — "I'd trade with you," "I'd hire you," "I'd acquire you." But that first signal is dangerous: the moment your intent leaks, the market front-runs you (MEV), or a one-sided approach becomes public and awkward. Today you either broadcast intent and eat the leak, or trust a middleman. We wanted to remove that trade-off entirely with cryptography.

What it does

  • Register an identity: your public key goes on-chain; your intent never does.
  • Express interest in a counterparty with a private reveal (terms/contact), encrypted on your device. Only an opaque tag, a nullifier, and ciphertext hit the chain — nothing about who-wants-whom.
  • Match: because two parties who point at each other derive the same tag with no communication, their submissions land in the same slot. When both have posted, it unlocks — and only they can decrypt each other's reveal.
  • "What the chain saw": a live ledger inspector proving the chain only ever held opaque tags — no identities, no intent.

How we built it

The core is non-interactive ECDH matching tags on Midnight's Jubjub curve. To signal interest in PK_T, you compute the shared secret s = sk·PK_T inside a zero-knowledge circuit and disclose only hash(s) (the slot "link"), a per-direction nullifier, and a client-side-encrypted payload. Diffie–Hellman (sk_A·PK_B = sk_B·PK_A) guarantees both sides derive the same link with zero coordination. A Compact smart contract holds the ledger (registry, match slots, nullifier set); TypeScript witnesses keep the secret key off-chain; the browser and CLI encrypt payloads with WebCrypto AES-GCM using the same runtime EC primitives the circuit uses, so off-chain and in-circuit math agree bit-for-bit.

Challenges we ran into

  • Compact has no in-circuit encryption — we moved encryption client-side and store a fixed-size opaque blob, keeping the circuit tiny.
  • The naive design leaked the target via an on-chain registry check; we removed it after realizing the nullifier alone prevents fake/self matches.
  • Midnight's embedded Jubjub scalar field is smaller than the base field — a subtle source of "EmbeddedFr" decode errors until we sized secrets correctly.

Accomplishments we're proud of

A genuinely novel primitive — no prior Midnight project builds a matching/ threshold-reveal escrow — with a full test suite (mutual match, one-sided secrecy, replay + self-match rejection, ECDH cross-decrypt) and a working end-to-end match on a real Midnight node.

What's next

Atomic shielded-swap settlement on match (private intent → private settlement), and the generalization to k-of-n threshold escrow (e.g. multi-accuser whistleblowing: a report surfaces only when several people independently name the same target).

Built With

Share this project:

Updates