A simple, fair exchange protocol

Alice has x bitcoins and Bob has y litecoins. Assuming that these amounts are roughly of equal value, they would like to conduct an atomic exchange, so that after a given time, either Alice has y litecoins and Bob has x bitcoins, or the transaction is aborted either by Alice or Bob and their positions are unchanged.

The protocol below enabling the atomic swap is an example of a "fair exchange" protocol, meaning neither Alice nor Bob need to trust each other or any intermediary.

In practice, Alice and Bob still need a venue to share their bid/ask offers with the world and to have them matched in a swap.
The venue can be a decentralized network such as the Lightning network or a centralized platform.
Our protocol is based on HTLCs (Hashed Timelock Contracts) that are used also by the Lightning network protocol but does not require interactions with the Lightning network.

We assume that both the Bitcoin and Litecoin chains are loosely synchronized to each other, such that neither chain gets significantly ahead of the other.
Both chains support the same scripting language, namely Bitcoin script, so that the same script can be used for both Bitcoin and Litecoin HTLCs.
In a future release, we will show that atomic swaps can be performed across chains with distinct scripting language, e.g. Bitcoin and Ethereum.

Phase 0: Alice and Bob are matched
Alice draws a random secret S and creates a bid offer with the hash of S and a public key, initiating a swap if a bitcoin utxo (amount x) corresponds to her public key.
Symmetrically, Bob creates an ask with the public key corresponding to his litecoin utxo (amount y).
Either Alice or Bob launch a search for a match and their bid/ask are matched:
Alice swap is updated and now points to Bob’s ask and Alice’s bid.
Note: a match can be found only if bid and ask amounts are within a 5% range.

Phase 1: Alice bails in

Alice constructs TX1 to bail in x BTC. Bitcoin transaction TX1 has a single txout, containing the following scriptPubkey:
// Ordinary claim for B
2 <pubkeyA> <pubkeyB>
// Refund for A
2 <pubkeyA> <pubkeyB>

Alice signs TX1 but does not yet publish it since her funds would be the lost without the cooperation of Bob.

She creates Bitcoin transaction TX2, spending the above script to her refund address A with a locktime of +48 hours. It contains TX1[0] as a txin, and the txout is a standard spend to A. The scriptSig for this txin looks like:
<sigB2> <sigA2> FALSE
which proceeds through the ELSE branch of the IF/ELSE/ENDIF guard clause. Alice signs TX2, obtaining sigA2.

Alice transmits TX2 to Bob, and requests that Bob signs and returns it. Once Alice receives Bob’s signature sigB2, then Alice publishes TX1, knowing that she would be able to claim her refund after 48 hours, as long as she does not reveal S. Alice is now bailed in.

Phase 2: Bob bails in

Bob received TX2 in the first phase, and therefore knows H(S). Bob also signed Alice’s refund transaction, but that will not be active until after 48 hours.
Unless he decides to abort the swap, Bob gets what he wants within 24 hours max.
Bob has also seen that Alice has bailed in since TX1 has been published in the Bitcoin blockchain.

Bob creates Litecoin transaction TX3, which bails in y LTC. TX3 is symmetric with TX1, and has a single txout, containing the same scriptPubkey as in Phase 1.

Bob also creates TX4, which is his own Litecoin refund. TX4 is timelocked for only 24 hours, uses TX3[0] as a txin, and the scriptSig looks like this:
<sigB4> <sigA4> FALSE
which proceeds through the ELSE branch of the script. Bob signs TX4, obtaining sigB4, and transmits TX4 to Alice, asking her to sign it.
When Bob receives sigA4, he can safely publish TX3, knowing that he would be able to abort and reclaim his litecoins after 24 hours. Bob is now bailed in.

Phase 3: Alice reveals S and triggers both transactions

Phase 3 starts with Alice sending her signature sigA6 over a transaction TX6 transferring the Bitcoin output of TX1 to Bob.
She knows Bob cannot complete the scriptSig unlocking TX6 because he does not know S yet.

After checking the validity of sigA6, Bob sends sigB5 to Alice, his signature over a transaction TX5 transferring the Litecoin output of TX3 to her.

Alice has 24 hours to claim the Litecoins, using the following scriptSig:

<sigA5><sigB5> <S> TRUE
which triggers the IF branch of the conditional. When publishing TX5, she reveals S to Bob in the Litecoin blockchain.

If Alice reveals S within 24 hours, then Bob can also claim his bitcoins before 48 hours:
<sigA6><sigB6> <S> TRUE

Bob can now collect his payment in bitcoins with TX6.
The swap is completed successfully when both TX5 is confirmed in the Litecoin blockchain and TX6 is confirmed in the Bitcoin blockchain.

If Alice disappears or does not publish TX5 within 24 hours, Bob can get his refund by publishing TX4 on the Litecoin blockchain.
Bob should not wait for the 48-hour TX2 locktime to expire because Alice could then publish both her TX2 refund and her TX5 payment.

Our protocol is safe for Bob if and only if the TX2 locktime is longer than the TX4 locktime by several hours (24 hours here in our example).
That is because TX5, if published before TX4, would spend the output of TX3 used to finance TX4:
publishing TX4 would then be seen by the Litecoin network as a double-spend attempt and would be rejected as such.

Conversely, if Bob disappears or does not send sigB6 to Alice within 48 hours, she can get her refund by publishing Bitcoin transaction TX2.
Because she did not publish TX5 yet, Bob has no way of knowing S and, as a result, he cannot validate Bitcoin transaction TX6.
TX6, if published before TX2, would spend the output of TX1 used to finance TX2:
publishing TX2 would then be seen by the Bitcoin network as a double-spend attempt and would be rejected as such.

To sum up:

Phase 1
TX1: Alice locks bitcoins in the HTLC smart contract
TX2: timelocked Bitcoin refund to Alice (broadcast only if swap is aborted)
Phase 2
TX3: Bob locks litecoins in the HTLC smart contract (symmetric to TX1 smart contract)
TX4: timelocked Litecoin refund to Bob (broadcast only if swap is aborted)
Phase 3
TX5: Litecoin payment to Alice
TX6: Bitcoin payment to Bob

What does locktime mean ?

We can use locktime to make sure that a transaction is locked until a specific block height, or a point in time.

Locktime < 500000000 Unlocked at block height.
Locktime >= 500000000 Unlocked at specific time (in Unix time)

In the latter case (a specific time is set), the transaction can only be relayed on the network after the median time of the last 11 blocks (according to the time field in their block headers) is greater than the set locktime.
As a result, if the locktime is set to, say, one hour from now, the transaction won't be mined until about two hours from now.
Also, for the locktime to be effective, one needs to set one of the sequence values (for one of the inputs in the transaction) to anything below the default maximum (0xffffffff).
If you do not want your transaction to be locked until a specific block or time, set the locktime field to 0x00000000 (or anything below the current block height or unix time).
Any attempt to broadcast a transaction before its locktime will only trigger the “64: non-final” network error message.

Bitcoin Wiki
Bitcointalk Forum

Please note that the application does NOT store any private key or secret,
only public key(s), expiry date(s) and hash(es) required by the script.
Make sure to backup and store your private keys and/or secrets securely before funding your P2SH address.
Do not use this application to move large sums of money: this is only a demo tutorial, not a commercial site!

Need help? Contact me at pierre dot noizat at paymium dot com
Need bitcoins ? Sign up at paymium.com !

If the application doesn't work as expected, please report an issue.
and include the diagnostics.

This application was developed using the following free software:

* Ruby 2.5.3
* Rails 5.2.2
* btcruby, the awesome Bitcoin ruby library developped by Oleg Andreev and Ryan Smith.
* bitcoin-ruby, the equally awesome Bitcoin ruby library written and maintained by Julian Langschaedel. Special thanks to Shigeyuki Azuchi for his remarkable work on Segwit.

Getting Started with Atomic Swaps

To generate your own Bitcoin public/private key pairs, I recommend coinb.in or bitaddress.org

Similarly, to generate your own Litecoin public/private key pairs, you may want to use liteaddress.org

The coins can be spent by supplying the required private keys (both WIF compressed and uncompressed formats are accepted). Then you can broadcast the cashout transactions to the Bitcoin and Litecoin networks.

Alice must supply the secret S corresponding to the HASH160(S) hash.

Depending on the set time conditions (locktime), the network will either reject the signed spending transaction as non-final or confirm it.

If the time conditions are not met, the network nodes will return an error message like "Locktime requirement not satisfied" or "non-final".

The current locktime for atomic swaps on atomic.bitcoinscri.pt is set to 24 hours.


© Pierre Noizat - 2015-2019 Source code soon to be released under the MIT license