Example of a HTLC P2SH
Cross-Chain Atomic Swap Between a Ravencoin Asset and
BTC
*Another step towards making Ravencoin a
full-feature fair permissionless proof-of-work
distributed exchange*
Overview:
The Proof-of-Concept (POC) shown here is an atomic swap in
which tokens are purchased on the Ravencoin block chain in
exchange for bitcoin on the bitcoin blockchain. Since this
capability is not yet live on Ravencoin mainnet, this POC
exchange is between Ravencoin testnet-7 and Bitcoin
testnet-3.
How is this possible?:
This functionality is enabled by the new P2SH code currently
running on testnet which is planned for mainnet release.
This same code will also make it possible to lock assets
into Multi-signature contracts.
The details:
All transactions were sent using:
-raven-qt from Raven Core version v4.7.0.0-c05c88147 (linux
64-bit) on Ravencoin testnet-7
-which is currently available as an
"artifact" from
https://github.com/RavenProject/Ravencoin/pull/1063/checks
-bitcoin-qt from Bitcoin Core version v0.21.1 on Bitcoin
testnet-3
The desired cross-chain atomic swap can be fully
described as:
-Alice has 0.02 bitcoins and wants to buy 2 TEST_TOKEN
ravencoin assets for 0.01 bitcoins total (0.005 bitcoins
each)
-Alice's 0.02 bitcoin are in
alice_bitcoin_address. She will use this address to pay for
the tokens and for any bitcoin fees
-Alice also has 20 RVN in
alice_ravencoin_address from which she will draw any RVN
transaction fees
-Alice wants her two purchased tokens to
end up in in alice_ravencoin_address
-Bob has 5 TEST_TOKEN ravencoin assets and wants to sell 2
of them for .01 bitcoins total (0.005 bitcoins each)
-Bob's 5 tokens are in
bob_ravencoin_address.
-Bob also has 10 RVN in
bob_ravencoin_address from which he will draw any RVN
transaction fees
-Bob wants his bitcoin to end up in
bob_bitcoin_address. Any bitcoin transaction fees will be
substracted from his payment
For this POC, the following addresses were used and were
initialized to hold BTC, RVN, and TEST_TOKEN assets as
described above:
alice_btc_address = 'n1BTMRfeWnZxfeVtd1zr3HkMA1hhHC5fPo'
alice_rvn_address = 'mfzGMgmZtnvZEETHSCnY7zfSGMKkGy25Bt'
bob_rvn_address = 'n1rL8uj6ZdP4c1SJtvk6HLoz1phoQS6NwA'
bob_btc_address = 'mqfu4jxaCF2H1Y2HjbRn2xsyVMd8GtkHN3'
The cross-chain atomic swap takes place in the
following steps:
1) Alice starts the process by:
a) Selecting a random 32-byte secret.
b) Using bitcoin script to write an HTLC
contract which will lock up her BTC payment for the tokens
she wants to buy.
c) She then calculates and sends the
INITIATE transaction on the Bitcoin blockchain.
Alice's transaction uses P2SH to lock her
BTC payment into an HTLC contract.
The HTLC scriptPubKey is written in such
a way that it can be spent by a signature from Bob's BTC
address key (if Bob completes the swap), or by Alice's BTC
address key (if the swap is cancelled and Alice takes her
refund). Spending to Bob is locked by Hash(secret), the hash
of the secret Alice chose. Spending to herself is locked 48
hours into the future.
2) Alice then communicates with Bob by Direct-Messaging
to send him:
a) The transaction number of her INITIATE
transaction, and
b) The full code of her HTLC
contract stript
In this POC, Alice's INITIATE transaction
on the BTC blockchain is:
d8cc99ba3531d69d2986bb71ce60246f3a4c8eb9c8eced29b8d917e76fdf8599
which anyone can view at:
https://bitpay.com/insight/#/BTC/testnet/tx/d8cc99ba3531d69d2986bb71ce60246f3a4c8eb9c8eced29b8d917e76fdf8599
to see that it locks her 0.1 BTC payment
into a P2SH contract at address:
2MvgFdqypg9UPdyty7LPirTnRyWgFUJxVqS
In this POC, the full code of Alice's
HTLC contract is:
63a6141373a1cacbb7ef1520cc3b81cde6c5a0085efb4b8876a9146f624e3d29d9caaeffefe0c9bb383af9d
754484d6704ebe70261b17576a914d7b273f4b82ae919c21359dd5a2a159019bd75ce6888ac
Bob can calculate that the Hash160 of
that contract matches the Hash160 used in the P2SH of the
INITIATE transaction, which proves that Alice indeed gave
him the correct contract used in that transaction.
Then Bob can examine the contract in his
bitcoin-qt node using the "decodescript" command to see the
contract code:
OP_IF OP_RIPEMD160
1373a1cacbb7ef1520cc3b81cde6c5a0085efb4b
= 20-byte
Hash(secret)
OP_EQUALVERIFY
OP_DUP
OP_HASH160
6f624e3d29d9caaeffefe0c9bb383af9d754484d
= Hash160 of
Bob's BTC REDEEM address
1627580395
= 48 hours in the future in Unix time
OP_DROP
OP_HASH160
d7b273f4b82ae919c21359dd5a2a159019bd75ce
= Hash160 of Alice's BTC REFUND address
OP_ENDIF
OP_EQUALVERIFY
OP_CHECKSIG
So Bob was able to verify that the
contract sends to the correct addresses.
Bob was also able to see Hash(secret)
which is locking up the BTC payment he wants to receive.
Since Alice held up her end of the
bargain, it is Bob's turn to proceed.
3) Bob then proceeds by:
a) Using ravencoin script to write an
HTLC contract which will lock up his TEST_TOKEN assets which
he wants to sell
b) He then calculates and sends the
PARTICIPATE transaction on the Ravencoin blockchain
(See the next step for the details about
the PARTICIPATE transaction.)
Bob's transaction uses P2SH to lock his
TEST_TOKEN assets into an HTLC contract.
The HTLC scriptPubKey is written in such
a way that it can be spent by a signature from Alice's RVN
address key (if Alice completes the swap), or by Bob's RVN
address key (if the swap is cancelled and Bob takes back his
token refund).
Spending to Alice is
locked by the same Hash(secret) which Alice used. Bob
doesn't know "secret", but he saw Hash(secret) in the
contract.
Spending to himself is
locked 24 hours into the future.
4) Bob then communicates with Alice by Direct-Messaging
to send her:
a) The transaction number of his
PARTICIPATE transaction, and
b) The full code of his HTLC contract
stript
In this POC, Bob's PARTICIPATE
transaction on the RVN blockchain is:
e1b6b297c0ad01430776e92c8a459cf16c33a869a291d2d6f15f0d0737b5541c
which anyone can view at:
https://rvnt.cryptoscope.io/tx/?txid=e1b6b297c0ad01430776e92c8a459cf16c33a869a291d2d6f15f0d0737b5541c
to see that it locks two of his
TEST_TOKEN assets into a P2SH contract at address:
2MvgFdqypg9UPdyty7LPirTnRyWgFUJxVqS
In this POC, the full code of Bob's HTLC
contract is:
63a6141373a1cacbb7ef1520cc3b81cde6c5a0085efb4b8876a914052a4f138092893ca600055779
f53a4d817e8ad867046c960161b17576a914df0ca6eab43a2cfd3660b8a2f5f36ea03093c3626888ac
Alice can calculate that the Hash160 of
that contract matches the Hash160 used in the P2SH of the
PARTICIPATE transaction, which proves that Bob indeed gave
her the correct contract used in that transaction.
Alice can examine the contract using her
raven-qt node "decodescript" command to verify that it
contains the correct addresses and terms.
Since Bob held up his end of the bargain,
Alice can go ahead and do the deal.
5) Alice then calculates and sends her INITIATOR_REDEEM
transaction on the Ravencoin blockchain, in which she take
possession of the TEST_TOKEN assets she bought.
In this POC, Alice's INITIATOR_REDEEM
transaction on the RVN blockchain is:
31d4c2f66d74ab466e736cd4bb9333490491ed5110dcc7211c04952ca9d6ba4a
which anyone can view at:
https://rvnt.cryptoscope.io/tx/?txid=31d4c2f66d74ab466e736cd4bb9333490491ed5110dcc7211c04952ca9d6ba4a
to see that the 2 TEST_TOKEN assets she
purchased have been transferred into her Ravencoin address
If you carefully study this REDEEM
transaction, you should focus on the scriptSig of input
Vin[1] which is used to unlock Bob's P2SH contract.
That scriptSig which Alice calculated
has the following form:
Signature using the
key for Alice's RVN address
SIGHASH_ALL
The PubKey of Alice's
RVN address
The full 32-byte
secret which Alice chose at the beginning
OP_1 (a "True" which
indicates that the first clause in the contract is being
chosen)
The full 81-byte
contract which Bob provided
Note that in order to take possession of
the TEST_TOKEN asset which she purchase, Alice had to reveal
the "secret" to the world by including it in plain text in
this transaction.
6) Bob can now calculate and send his PARTICIPATOR_REDEEM
transaction on the Bitcoin blockchain, in which he take
possession of 0.01 Bitcoin which Alice paid for
his TEST_TOKEN assets.
In this POC, Bob's PARTICIPATOR_REDEEM
transaction on the BTC blockchain is:
d7872f41dc29c4407ea6755aae375ffd0fcaba8b6046b26729b13b0c573c5fae
which anyone can view at:
https://bitpay.com/insight/#/BTC/testnet/tx/d7872f41dc29c4407ea6755aae375ffd0fcaba8b6046b26729b13b0c573c5fae
to see that the 0.01 BTC payment from
Alice (minus a BTC transaction fee) has been transferred
into his BTC address
THAT'S IT !!! EASY-PEASY (well... sort of)
!!! Most importantly - No Trust Is Required
Note that if either Bob or Alice, or both, had become
uncooperative or unavailable at any time during the swap,
the activity could have been unwound using an
INITIATOR_REFUND transaction (after 48 hours) and/or a
PARTICIPATOR_REFUND transaction (after 24 hours).
The format of REFUND transactions are similar to the REDEEM
transactions, except that the scriptSigs use OP_0 opcode (to
select the 2nd clause in the contract), and don't need to
include the "secret"
Copyright 2021 by Hans Schmidt