Open for pickup: an Aiken escrow (v0.7) for trustless ADA ↔ shielded ZEC swaps (simulator-tested, never tested on chain)
Hi Cardano devs,
I’ve been researching zeUTXO, a trustless atomic swap between ADA and shielded Zcash. I’m stepping back now and opening the repo for anyone who wants to continue it or reuse parts.
Repo: GitHub - maybejb200/zeUTXO-zcash-cardano-atomic-swap: Research prototype: trustless private atomic swap between shielded Zcash and Cardano using adaptor signatures, cross-group DLEQ and an Aiken escrow (simulator only, paused) · GitHub (MIT OR Apache-2.0). Start with HANDOFF.md.
The hook: one PlutusV3 escrow that holds all the clocks
The Cardano side is a single Aiken escrow, v0.7 (PlutusV3, about 2.4 KB, script hash 0ed9e0540ff4f40ccf3ccad91efaf9663d0feb4a6b5cad63700087e0). The Zcash side has no timelocks. Alice locks ADA; Bob funds a shielded note to a 2-of-2 joint key. Whoever learns the other’s share takes the ZEC, so Cardano never verifies Zcash: no light client, relay or oracle.
The escrow’s state machine:
- Two-step claim:
Commit{go_sig}moves Open → Claimed. It checks Alice’s Ed25519 “go” signature (bound to swap id, script hash, outref, amount and T1) and carries no secret. ThenReveal{b}checksb·G1 == b_con BLS12-381 and pays Bob. If Bob commits and stalls,Escapeafter T3 returns the ADA to Alice. - Two-step refund:
Noticemoves Open → Refunding and writes t4 into the datum. It carries no secret. ThenRefundReveal{a}returns the ADA to Alice. If she never reveals,Forfeitafter t4 pays Bob. - The invariant: no secret-carrying redeemer has a deadline, and no deadline-bound redeemer carries a secret. That’s what defeats the “censor the reveal until the timeout” attacks.
- Each spend has exactly one escrow input. Continuing outputs keep the same address and value, a byte-equal inline datum, and no reference script.
A cross-group DLEQ proof (Pallas ↔ BLS12-381 G1) ties the shares committed in the datum to the Zcash key.
Honest status
This is simulator-only. Local tests suggest it might be possible, but it has never been tested on chain. No preprod or testnet swap has run.
aiken check: 71/71 (76 with extra review tests). The included CI workflow rebuilds the escrow with Aiken v1.1.24 and checks that it’s byte-identical to the committedplutus.jsonand its pinned hash.- The end-to-end simulator (Lucid Evolution emulator plus a stricter ledger wrapper) passes 727/727 checks in two parameter profiles.
- Seven internal adversarial reviews; none is an independent audit.
- A testnet rehearsal on preprod + Zcash testnet was started on Nov 9–11 but never reached a swap. The Zcash node I was running kept stalling and never finished syncing.
Where Cardano folks could help
- Running the rehearsal on preprod and checking things the emulator can’t: validity-interval and slot rounding on the Notice (fixed in code, emulator-tested only), and map-encoded redeemers in Conway transactions.
- Writing a small live-run driver around the existing Lucid Evolution / Koios off-chain code.
- Reviewing the escrow itself. An independent review of
escrow.akwould be very welcome. - Review 6 suggested an in-escrow refundable deposit, which would change the script.
If this is at all interesting, I’d love to hear about it.
— John (maybejb200)