Skip to content

Instantly share code, notes, and snippets.

Last active November 23, 2023 19:54
Show Gist options
  • Save markblundeberg/ee027cb12b1e882145bebcd658a1630f to your computer and use it in GitHub Desktop.
Save markblundeberg/ee027cb12b1e882145bebcd658a1630f to your computer and use it in GitHub Desktop.
SwapChannels: hide your atomic swaps using ordinary payment channels

SwapChannels: hide your atomic swaps using ordinary payment channels

Dr. Mark B Lundeberg, 2018 July 13 bitcoincash:qqy9myvyt7qffgye5a2mn2vn8ry95qm6asy40ptgx2

Earlier this year I posted an advisory on a possible attack on certain cross-cryptocurrency atomic swap contracts. This time I'd like to discuss the anonymity problem of atomic swaps and how it can be simply mitigated.

Problem: The standard hash-based atomic swap leaves a very noisy fingerprint on the blockchain, which 1) is obviously an atomic swap, and 2) includes a unique unlock value k. The same unique k will be identical on both blockchains, so any future blockchain analysis will be trivially able to link the two sides of the swap. It would be nice if atomic swaps looked more like ordinary transactions and did not have such an obvious linkage.

The Lightning payment channel network actually offers a solution to this, in that the secret k is unlikely to be published except in fallback. Here I'd like to simplify this idea to bare-bones and explain how even for direct atomic swaps, it's better to perform them using purpose-made ordinary payment channels (that do not even require a malleability fix). The advantages of these SwapChannels over regular atomic swaps: more concealed, twice as fast to set up, and ability for trustless high frequency trades. Disadvantage: ~5% more blockchain cost.


Rather than the bitcoin script in my previous post, it's more appropriate to use a diagrammatic representation this time. Arrows represent transactions, and boxes represent transaction outputs. To avoid cluttering the diagrams, change outputs will be omitted.

When a box has multiple arrows emanating from it, that means multiple alternative transactions that could occur (only one of these alternatives may be actually published onto the blockchain). Dashed arrows and boxes will be used to mark the parts that will not usually be published on chain, and thus remain secret.

The content of the box is the meaning of its script (smart contract), that is, which pieces are required to spend (unlock) the output. The text along an arrow denotes the pieces that are actually used to unlock the output. The following pieces are involved:

  • A: a valid signature from a key owned by Alice.
  • B: a valid signature from a key owned by Bob.
  • k, k1, k2, etc.: a correct unlock value (a preimage of given size that reproduces a given hash).
  • t1: a fallback time t1 has expired. (this is used for guaranteed refunds)
  • t2: a fallback time t2 has expired. In all the examples below, t1 < t2 is required for security reasons.

A boolean expression like A & (B | t1) would mean that Alice's signature is required to spend, but additionally, either Bob must sign or time t1 must have passed.

Review: hash locked atomic swaps

Diagram of normal atomic swap

For simplicity, a 1:1 exchange rate between cryptocurrencies is taken.

  1. Alice and Bob provide public keys each other. Alice generates secret k.
  2. Alice funds PA.
  3. PA is published & confirmed on its blockchain.
  4. Bob funds PB, without yet knowing k.
  5. PB is published & confirmed on its blockchain.
  6. Alice spends PB, thereby revealing k.
  7. Bob now knows k and spends PA.

If the procedure breaks down before step 6, Bob waits until t1 to get his refund, then Alice gets her refund after t2.

Review: unidirectional payment channels

Diagram of normal payment channel

  1. Bob sends a public key to Alice.
  2. Alice funds PC.
  3. PC is published & confirmed on blockchain.
  4. Alice creates a payment and signs it, then sends this incomplete transaction to Bob. (It cannot be published without Bob's signature.)
  5. Step 4 may be repeated any number of times, with incremental payments.
  6. To finalize, Bob takes the most recent payment, then signs and publishes it.

For these unidirectional payment channels, each of the payments must be incrementing in value, as Bob is free to publish the highest-value one he has seen. If Bob stops responding, then Alice can get back a full refund after time t1.

SwapChannels: hidden Atomic swaps in payment channels

Diagram of SwapChannels

*Summary: starts out like two ordinary payment channels but the off-chain payments are now atomic swap contracts.

  1. Alice and Bob provide public keys to each other.
  2. Alice and Bob fund payment channels to each other (PCA and PCB), on their respective blockchains.
  3. PCA and PCB are each published and confirmed on their respective blockchains.
  4. Alice generates secret k1 and signs a payment that would produce output PA1, and sends this incomplete transaction to Bob. Bob does not sign yet.
  5. Bob signs a payment that would produce output PB1, and sends this incomplete transaction to Alice. Alice does not sign yet, however she reveals k1 to Bob, thereby locking in the swap.fn1
  6. Steps 4,5 may be repeated any number of times, with incrementing payments and new values k2, k3, etc..fn1
  7. To finalize, Alice and Bob each sign and send each other an ordinary (non-hash-locked) payment with value equal to the previous payment. They then countersign and publish the results.

Under normal completion, the resultant appearance on each blockchain is that of a regular payment channel opening then closing, which makes each side significantly more difficult to link. As a fallback, the participants end up signing then publishing the hash-lock states created in steps 4,5.



(For simplicity: focussing on bitcoin script; neglecting change outputs; 71 byte DER signatures, 33 byte pubkeys, 34 byte txouts)

A regular Alice->Bob transaction costs ~190 bytes.

The normal atomic swap opening and closing costs ~470–510 bytes published onto each blockchain, depending on how efficiently the script is coded.fn2

A normal payment channel opening and closing costs ~500–550 bytes, depending on how efficiently the script is coded.fn2

For normal completion, the SwapChannel costs the same as a normal payment channel, i.e., ~500–550 bytes, per blockchain. If it completes abnormally (with hash locks published), then an additional transaction with cost of ~280–320 bytes will need to happen to move funds out of the hash locks.

Time cost: with SwapChannel, Alice's and Bob's payment channels need to be confirmed before any swaps take place, however both may start their channels at the same time. This is twice as fast as a regular atomic swap, where Alice's funding transaction must be confirmed before Bob can post his side, and Bob's transaction must be confirmed before Alice can complete the swap.

Better swaps for volatile / high-frequency trades

Nakamoto's original proposal for payment channels suggested an application in high-frequency trading. Unfortunately if regular payment channel procedures are used for cross-chain trading, one party could cheat by simply not reciprocating for the last payment and thereby steal some amount of funds.

Regular atomic swaps remove the ability to cheatfn3 but unfortunately are not at all suitable for high frequency trading, since the trading price would be baked in at the setup time -- at least 2 blockchain confirmations before the trade takes place. This is long enough that volatility would invalidate the initial pricing.

SwapChannels allows trustlessfn3 high-frequency atomic cross-cryptocurrency trades between two parties. The reason is that although it does require a setup, the price of trade is not fixed at the start. Actual trades can then occur with the instantaneous trading price.

Incentives for finalizing normally

It is interesting to consider what are the incentives of each party to provide a final exit transaction to the other party, in the last step of SwapChannel. Obviously if both fail to do this, then the punishment is having a publicly visible fingerprint of the atomic swap that directly links the parties, which is undesirable for both.

Let's say that Bob goes first, providing Alice with a normal exit. Alice might simply refuse to reciprocate, which would mean that that Bob would have to publish the version with hash lock and then also pay an additional transaction fee to gain full control (see Costs). There is also a small moral hazard in this case: Alice could demand a tiny ransom for providing Bob a normal exit, by slightly reducing the exit payment offered to him.

That said, a withholding Alice would not be entirely free of penalty: it would be revealed Alice had sent money into an atomic swap, which encourages a search for a correlated payment channel and may reveal her newly acquired funds.

Multi-swaps: multiple payment channels / cryptocurrencies swapped at once

In the SwapChannel protocol, there is not direct linkage, however there is still the possibility of a weaker correlation linkage, due to similar-valued payment channels opening and closing at similar times on different blockchains.

For this purpose it is helpful to introduce atomic multi-swaps. Alice and Bob can create multiple payment channels to each other (on multiple cryptocurrencies if they wish). For security, Alice's channels must each expire after all of Bob's channels would expire. In each swap, Alice can offer a bouquet of payments of varying value on each channel, but all with the same hash lock k. Bob can reply with another bouquet under the same hash lock. Once Alice provides k the swap is locked in. The two bouquets do not need to have identical ratios, only similar-valued totals.

By staggering the opening and closing times, as well as using multi-channel swaps to obfuscate the total value, the channels will become less obviously correlated. If there is a background of many payment channels opening and closing on each blockchain, then it could be made quite difficult to detect that a swap has occurred. Such a multichannel strategy might even be useful for swaps within a single cryptocurrency, being used to break the link in blockchain analysis.


fn1: If Alice used the same k for all payment states, Bob could trick her by not reciprocating after her last payment, which forces her to choose between taking a loss (Alice publishes PBN-1 onto the blockchain, after which Bob knows k and gets PAN) or to withhold k and wait for a complete refund. Likewise, Bob may play fair but Alice could decide to undo all the swaps by simply not revealing k at the end. Instead Alice should reveal k after each swap, which locks it in (Bob can now redeem the payment at any time he wishes). Since it is revealed, Alice must of course choose a new secret k for the next round, which also neatly prevents Bob from playing the aforementioned trick. Fortunately, the participants need only remember the most recent (highest-valued) locked-in state and its k value.

fn2: Bitcoin P2SH script sizes can vary depending on whether the address is entered as a 20-byte hash in the P2SH script, or directly as the 33-byte public key. The former option requires three more opcodes (DUP HASH160 EQUALVERIFY) and the 33-byte public key (+1 more byte PUSH) must anyway be placed in the scriptSig, meaning that the former option adds 24 unnecessary bytes. Likewise, the atomic swap secret sizes and hash-secret sizes are completely secure at 16 and 20 bytes respectively but some choose to use 32 and 32 bytes instead -- adding 29 unnecessary bytes (16 + 12 + 1 byte extra in the secret size check).

fn3: With all atomic swap protocols (including SwapChannels), there appears to be a weaker hazard, in that Alice may request a trade and then fail to promptly provide k to Bob, which lets her unilaterally put off the choice of either taking the trade, or to wait for refund time and not take the trade at all. In other words, Bob is actually providing Alice a short term financial option for free (after t1 she loses the option). With SwapChannels, a distrusting Bob should take advantage of payment channel structure, by gradually build up the swap in small increments. At worst she can now only withhold k on the last increment, keeping a tiny option value at the cost of locking up all of her funds in the channel.

Copy link

gmaxwell commented Jul 14, 2018 (required a few more steps because that was written before CSV made the refund cases for channels simpler), also prior lightning discussion pointed out that arbitrary contracts could be done in channels-- so it's no accident. :) An implementation of coinswaps is over at ... and one of the major design objectives for work on new checksig's for Bitcoin is enabling and simplifying scriptless scripts so that swaps and channels can be implemented with minimal round trips in a manner that looks indistinguishable from ordinary non-channel one key payments ( ).

Copy link

Ah, fantastic, I see someone smart has thought of this idea before me. :D

Copy link

Version 2 posted: stressed importance of using a new k value for each swap within a payment channel (and updated figure appropriately), after reddit discussion with Andrew Stone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment