The conditional swap is an N:M primitive that extends Anchr's 1:1 atomic swap to support binary-outcome markets. Matched pairs lock tokens in opposite directions. The Oracle reveals the winning preimage; the winner redeems the loser's tokens.
Anchr's core protocol is a 1:1 atomic swap: one Requester pays one Worker for one proof. The conditional swap generalizes this to N:M — multiple parties bet against each other on a binary outcome, with the Oracle resolving which side wins.
Use cases: two-party binary bets, insurance, group bounties, auctions.
The Oracle generates two preimages for two mutually exclusive outcomes:
| Outcome | Preimage | Hash |
|---|---|---|
| A (e.g., YES) | preimage_a |
hash_a = SHA-256(preimage_a) |
| B (e.g., NO) | preimage_b |
hash_b = SHA-256(preimage_b) |
Both hashes are published at market creation. The Oracle reveals exactly one preimage at resolution.
| Field | Description |
|---|---|
swap_id |
Unique swap identifier |
hash_a |
SHA-256 hash for outcome A |
hash_b |
SHA-256 hash for outcome B |
locktime |
Unix timestamp; after this, both sides refund |
Participants are matched into pairs. Each pair consists of two parties betting on opposite outcomes.
| Field | Description |
|---|---|
pair_id |
Unique pair identifier |
swap_id |
Parent swap |
party_a_pubkey |
Party A's public key (bets on outcome A) |
party_b_pubkey |
Party B's public key (bets on outcome B) |
amount_sats |
Amount locked by each party |
token_a_to_b |
Escrow token: A→B direction, redeemable by B if outcome B wins |
token_b_to_a |
Escrow token: B→A direction, redeemable by A if outcome A wins |
status |
pending, locked, settled_a, settled_b, expired |
Each party locks a Cashu token to the opposite outcome's hash:
- Party A locks
token_a_to_bwith conditionhash_b + Party B's pubkey - Party B locks
token_b_to_awith conditionhash_a + Party A's pubkey
This ensures:
- If outcome A wins: Oracle reveals
preimage_a. Party A redeemstoken_b_to_ausingpreimage_a + Party A's signature. - If outcome B wins: Oracle reveals
preimage_b. Party B redeemstoken_a_to_busingpreimage_b + Party B's signature. - If timeout: Both tokens refund to their original owners.
- The Oracle fetches verifiable data (e.g., TLSNotary proof of a price feed).
- The Oracle evaluates the outcome condition against the verified data.
- The Oracle reveals exactly one preimage (
preimage_aorpreimage_b). - Winners redeem escrow tokens from their matched pairs.
pending --> locked --> settled_a (outcome A won)
--> settled_b (outcome B won)
--> expired (locktime reached)
A Coordinator maintains an order book and proposes matches. The Coordinator can be a market maker, a relay operator, or a self-hosted service.
The Coordinator is NOT trusted with funds. It cannot steal tokens because escrow conditions are bound to hash preimages that only the Oracle controls. The Coordinator is a convenience layer for pairing participants.
The order book collects open orders from participants:
| Field | Description |
|---|---|
id |
Unique order identifier |
market_id |
Which swap/market this order belongs to |
side |
yes (outcome A) or no (outcome B) |
pubkey |
Participant's public key |
amount_sats |
Total amount to bet |
remaining_sats |
Amount not yet matched |
timestamp |
Order creation time |
Operations:
addOrder(order)— add to the bookcancelOrder(id)— remove before matchinggetOpenOrders(market_id, side?)— list open ordersmatchOrders(market_id)— run matching algorithm
The default algorithm is greedy FIFO: earliest orders are matched first. For each YES/NO pair:
- Take the earliest unmatched YES order and earliest unmatched NO order.
- Match amount =
min(yes.remaining_sats, no.remaining_sats). - Produce a
MatchProposal { yes_order_id, no_order_id, amount_sats }. - Reduce
remaining_satson both orders. - Orders with
remaining_sats > 0stay in the book (partial fill).
Other algorithms (pro-rata, CLOB) are permitted — the protocol does not prescribe the matching strategy.
For each MatchProposal, the Coordinator:
- Collects Cashu proofs from both parties.
- Creates cross-HTLC tokens via
createSwapPairTokens(see Token Locking above). - Returns the locked
SwapPairto both parties.
Both parties can verify match fairness by checking that their locked amount matches the proposal and that escrow conditions reference the correct hashes and pubkeys.
An alternative to HTLC preimage-based conditional swaps that uses FROST threshold signatures for Oracle attestation. Preferred when the Oracle is a threshold group (t-of-n signers).
The HTLC preimage pattern requires the Oracle to hold and reveal a secret preimage. With FROST P2PK, the Oracle instead holds keypairs and produces Schnorr signatures -- a more natural fit for threshold Oracle groups where no single party holds the full secret.
The Oracle generates two keypairs for the two mutually exclusive outcomes:
| Outcome | Secret Key | Public Key |
|---|---|---|
| A (e.g., YES) | sk_a (FROST group secret) |
group_pubkey_a |
| B (e.g., NO) | sk_b (FROST group secret) |
group_pubkey_b |
In production: these are FROST DKG-generated threshold keys requiring t-of-n signers to produce a signature. In demo mode: single Schnorr keypairs with a compatible interface.
Both public keys are published at market creation. The Oracle signs with exactly one key at resolution.
| Field | Description |
|---|---|
swap_id |
Unique swap identifier |
group_pubkey_a |
FROST group pubkey for outcome A |
group_pubkey_b |
FROST group pubkey for outcome B |
locktime |
Unix timestamp; after this, both sides refund |
Each party locks a Cashu token to the opposite outcome's group pubkey plus the counterparty's personal key:
- Party A locks
token_a_to_bwithP2PK([group_pubkey_b, Party B's pubkey], n_sigs=2) - Party B locks
token_b_to_awithP2PK([group_pubkey_a, Party A's pubkey], n_sigs=2)
This ensures:
- If outcome A wins: Oracle signs with
sk_a. Party A redeemstoken_b_to_ausingoracle_signature + Party A's signature. - If outcome B wins: Oracle signs with
sk_b. Party B redeemstoken_a_to_busingoracle_signature + Party B's signature. - If timeout: Both tokens refund to their original owners.
- The Oracle fetches verifiable data (e.g., TLSNotary proof of a price feed).
- The Oracle evaluates the outcome condition against the verified data.
- The Oracle signs a message with the winning outcome's group key.
- The losing side's secret key is permanently deleted.
- Winners attach the Oracle's signature + their own signature to redeem at the mint.
Without t-of-n Oracle agreement, neither group signature can be produced. This means:
- A single compromised signer cannot unlock tokens unilaterally.
- The locktime refund is the fallback if the Oracle group cannot reach threshold.
- The NUT-11 P2PK token on the Mint side is standard -- no Mint changes required.
create(swap_id) -> { pubkey_a, pubkey_b }
sign(swap_id, outcome, message) -> signature | null
getPubkeys(swap_id) -> { pubkey_a, pubkey_b } | null
has(swap_id) -> boolean
sign() is a one-time operation: the losing side's secret is permanently deleted, same irreversibility guarantee as HTLC preimage reveal.
The 1:1 bounty query (Specs 00-06) is the special case where N=1, M=1. The conditional swap extends this to N:M by:
- Replacing the single preimage with a dual-preimage scheme (or FROST P2PK dual-key).
- Introducing a matching layer that pairs participants.
- Using the same
EscrowProvider,verify(), and messaging infrastructure.
The Oracle's role is identical: verify data, produce an attestation, release the appropriate preimage or signature.
Cashu's standard NUTs (NUT-11 P2PK, NUT-14 HTLC) do not support conditional branching (IF outcome=A THEN pay X, ELSE pay Y). This limits the settlement options for conditional swaps:
| Settlement Mode | Oracle Fund Custody | Fair Exchange | Status |
|---|---|---|---|
| Oracle escrow (P2PK n_sigs=1) | Yes — t-of-n can steal | Not needed | Implemented |
| P2P cross-lock (P2PK n_sigs=2) | No — Oracle can't steal | Unsolved without trusted intermediary | Experimental |
| DLC on Cashu mint | No | Not needed | Proposed (PR #128) |
| DLC on Bitcoin L1 | No | Not needed | Roadmap |
The Oracle escrow mode is suitable for scenarios where the Oracle group (t-of-n FROST) is trusted. For trustless settlement where the Oracle cannot access funds, a DLC-based approach is required.
Anchr's Oracle verification (TLSNotary + FROST threshold signing) is independent of the settlement layer and works with any of the above modes.