RFC-310/Submarine Swap
Maintainer(s): S W van Heerden
Licence
Copyright 2021 The Tari Development Community
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of this document must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS DOCUMENT IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS", AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Language
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY" and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (covering RFC2119 and RFC8174) when, and only when, they appear in all capitals, as shown here.
Disclaimer
This document and its content are intended for information purposes only and may be subject to change or update without notice.
This document may include preliminary concepts that may or may not be in the process of being developed by the Tari community. The release of this document is intended solely for review and discussion by the community of the technological merits of the potential system outlined herein.
Goals
This Request for Comment (RFC) aims to describe how an Atomic swap between Tari and Minotari will be created.
Related Requests for Comment
$$ \newcommand{\script}{\alpha} % utxo script \newcommand{\input}{ \theta } \newcommand{\cat}{\Vert} \newcommand{\so}{\gamma} % script offset \newcommand{\hash}[1]{\mathrm{H}\bigl({#1}\bigr)} $$
Comments
Any comments, changes or questions to this PR can be made in one of the following ways:
- Create a new PR on the Tari project Github pull requests.
- Create a new issue on the Tari project Github issues.
Description
To be able to exchange Tari and Minotari without the use of some centralized exchange service, we need to do Submarine swaps or Atomic swaps between the two. We want to keep Tari as bare bones as possible with if possible just a commitment and perhaps a range proof, this means that we will not have access to smart contract features typically required for doing submarine swaps. This does not mean it is not possible to do atomic swaps with non-smart contract coins, look at RFC-0241: AtomicSwap XMR to see how this is done with Minotari and Monero.
Method
The primary, happy path outline of a Tari - Minotari submarine swap is described here, and more detail will follow. We assume that Alice wants to trade her Minotari for Bob's Tari.
- Negotiation - Both parties negotiate the value and other details of the Tari and Minotari commitments.
- Commitment - Both parties commit to the keys, nonces, inputs, and outputs to use for the transaction.
- Minotari payment - Alice makes the Minotari payment to a UTXO containing a "special" script described below.
- Tari Payment - The Tari payment is made to a multiparty scriptless script commitment.
- Claim Minotari - Bob redeems the Minotari, and in doing so, reveals the Tari private key to Alice only.
- Claim Tari - Alice may claim the Tari using the revealed key.
Please take note of the notation used in TariScript and specifically notation used on the signatures on the transaction inputs and on the signatures on the transaction outputs. We will note other notations in the Notation section.
TL;DR
The scheme revolves around Alice, who wants to exchange her Minotari for Bob's Tari. Because they don't trust each other, they have to commit some information to do the exchange. And if something goes wrong here, we want to ensure that we can refund both parties either in Tari or Minotari.
How this works is that Alice and Bob create a shared output on both chains. The Tari output is a simple aggregate key to unlock the commitment, while multiple keys are needed to unlock the Minotari UTXO. An aggregate key locks this Tari commitment that neither Alice nor Bob knows, but they both know half of the key. The current Minotari block height determines the unlocking key for the Minotari UTXO.
The process is started by Alice and Bob exchanging and committing to some information. Alice is the first to publish a transaction, which creates the Minotari UTXO. If Bob is happy that the Minotari UTXO has been mined and verifies all the information, he will publish a transaction to create the Tari commitment.
The TariScript script on the UTXO ensures that they will have to reveal their portion of the Tari key when either Alice or Bob spends this. This disclosure allows the other party to claim the Tari by being the only one to own the complete Tari aggregate key.
The script will ensure that at any point in time, at least someone can claim the Minotari UTXO, and if that person does so, the other party can claim the Tari commitment by looking at the spending data. It has two lock heights, determining who can claim the Minotari UTXO if the happy path fails. Before the first lock height, only Bob can claim the Tari; we call this the swap transaction.
If Bob disappears after Alice has posted the Minotari UTXO, Alice can claim the Minotari after the first lock height and before the second lock height; we call this the refund transaction. It ensures that Alice can reclaim her Minotari if Bob disappears, and if Bob reappears, he can reclaim his Tari.
That leaves us with the scenario where Alice disappears after Bob posts the Tari transaction, in which case we need to protect Bob. After the second lock height, only Bob can claim the Minotari; we call this the lapse transaction. The lapse transaction will reveal Bob's Tari key so that if Alice reappears, she can claim the Tari.
Heights, Security, and other considerations
We need to consider a few things for this to be secure, as there are possible scenarios that can reduce the security in the atomic swap.
When looking at the two lock heights, the first lock height should be sufficiently large enough to give ample time for Alice to post the Tari UTXO transaction and for it to be mined with a safe number of confirmations, and for Bob to post the Tari transaction and for it to be mined with a safe number of confirmations. The second lock height should give ample time for Alice after the first lock height to re-claim her Minotari. Larger heights here might make refunds slower, but it should be safer in giving more time to finalize this.
Allowing both to claim the Minotari after the second lock height is, on face value, a safer option. This can be done by enabling either party to claim the script with the lapse transaction. The counterparty can then claim the Tari. However, this will open up an attack vector to enable either party to claim the Tari while claiming the Minotari. Either party could trivially pull off such a scheme by performing a front-running attack and having a bit of luck. The counterparty monitors all broadcast transactions to base nodes. Upon identifying the lapse transaction, they do two things; in quick succession, broadcast their lapse transaction and the transaction to claim the Tari, both with sufficiently high fees. Base nodes will prefer to mine transactions with the higher fees, and thus the counterparty can walk away with both the Minotari and the Tari.
It is also possible to prevent the transaction from being mined after being submitted to the mempool. This can be caused by a combination of a too busy network, not enough fees, or a too-small period in the time locks. When one of these atomic swap transactions gets published to a mempool, we effectively already have all the details exposed. For the atomic swaps, it means we already revealed part of the Tari key, although the actual Minotari transaction has not been mined. But this is true for any HTLC or like script on any blockchain. But in the odd chance that this does happen whereby the fees are too little and time locks not enough, it should be possible to do a child-pays-for-parent transaction to bump up the fees on the transaction to get it mined and confirmed.
Key construction
Using multi-signatures with Schnorr signatures, we need to ensure that the keys are constructed so that key cancellation attacks are not possible. To do this, we create new keys from the chosen public keys \(K_a'\) and \(K_b'\)
$$ \begin{aligned} K_a &= \hash{\hash{K_a' \cat K_b'} \cat K_a' } * K_a' \\ k_a &= \hash{\hash{K_a' \cat K_b'} \cat K_a' } * k_a' \\ K_b &= \hash{\hash{K_a' \cat K_b'} \cat K_b' } * K_b' \\ k_b &= \hash{\hash{K_a' \cat K_b'} \cat K_b' } * k_b' \\ \end{aligned} \tag{1} $$
Key security
The risk of publicly exposing part of the Tari private key is still secure because of how ECC works. We can add two secret keys together and share the public version of both. And at the same time, we know that no one can calculate the secret key with just one part.
$$ \begin{aligned} (k_a + k_b) \cdot G &= k_a \cdot G + k_b \cdot G\\ (k_a + k_b) \cdot G &= K_a + K_b \\ (k_a + k_b) \cdot G &= K \\ \end{aligned} \tag{5} $$
We know that \(K\), \(K_a\), \(K_b\) are public. While \(k\), \(k_a\), \(k_b\) are all private.
But if we expose \(k_b\), we can try to do the following: $$ \begin{aligned} (k_a + k_b) \cdot G &= K_a + K_b\\ k_a \cdot G &= (K_a + K_b - k_b \cdot G) \\ k_a \cdot G &= K_a \\ \end{aligned} \tag{6} $$
However, this is the Elliptic-Curve Discrete Logarithm Problem, and there is no easy solution to solve this on current computer hardware. Thus this is still secure even though we leaked part of the secret key \(k\).
Method
Detail
We rely purely on TariScript to enforce the exposure of the private Tari aggregate keys. Based on Point Time Lock Contracts,
the script forces the spending party to supply their Tari private key part as input data to the script, evaluated via the operation ToRistrettoPoint
. This TariScript
operation will publicly reveal part of the aggregated Tari private key, but this is still secure: see Key security.
The simplicity of this method lies therein that the spending party creates all transactions on their own. Bob requires a pre-image from Alice to complete the swap transaction; Alice needs to verify that Bob published the Tari transaction and that everything is complete as they have agreed. If she is happy, she will provide Bob with the pre-image to claim the Tari UTXO.
TariScript
The Script used for the Tari UTXO is as follows:
ToRistrettoPoint
CheckHeight(height_1)
LtZero
IFTHEN
PushPubkey(X_b)
EqualVerify
HashSha256
PushHash(HASH256{pre_image})
EqualVerify
PushPubkey(K_{Sb})
Else
CheckHeight(height_2)
LtZero
IFTHEN
PushPubkey(X_a)
EqualVerify
PushPubkey(K_{Sa})
Else
PushPubkey(X_b)
EqualVerify
PushPubkey(K_{Sb})
ENDIF
ENDIF
Before height_1
, Bob can claim the Minotari UTXO by supplying pre_image
and his private Tari key part x_b
. After
height_1
but before height_2
, Alice can claim the Minotari UTXO by supplying her private Tari key part x_a
. After
height_2
, Bob can claim the Minotari UTXO by providing his private Tari key part x_b
.
Negotiation
Alice and Bob have to negotiate the exchange rate and the amount exchanged in the atomic swap. They also need to decide how the two UTXO's will look on the blockchain. To accomplish this, the following needs to be finalized:
- Amount of Minotari to swap for the amount of Tari
- Tari public key parts \(X_a\), \(X_b\) ,and its aggregate form \(X\)
- Minotari script key parts \(K_{Sa}\), \(K_{Sb}\)
- The TariScript to be used in the Minotari UTXO
- The blinding factor \(k_i\) for the Minotari UTXO, which can be a Diffie-Hellman between their Tari network addresses.
Key selection
Using (1), we create the Tari keys as they are multi-party aggregate keys. The Tari key parts for Alice and Bob is constructed as follows:
$$ \begin{aligned} X_a' &= x_a' \cdot G \\ X_b' &= x_b' \cdot G \\ x_a &= \hash{\hash{X_a' \cat X_b'} \cat X_a' } * x_a' \\ x_b &= \hash{\hash{X_a' \cat X_b'} \cat X_b' } * x_b' \\ x_a &= x_a \\ x_b &= x_b \\ X_a &= \hash{\hash{X_a' \cat X_b'} \cat X_a' } * X_a' \\ X_b &= \hash{\hash{X_a' \cat X_b'} \cat X_b' } * X_b' \\ x &= x_a + x_b + k_i \\ X &= X_a + X_b + k_i \cdot G_m\\ x &= x_a + x_b + k_i \\ X &= X_a + X_b + k_i \cdot G\\ \end{aligned} \tag{7} $$
Commitment phase
This phase allows Alice and Bob to commit to using their keys.
Starting values
Alice needs to provide Bob with the following:
- Script public key: \( K_{Sa}\)
- Tari public key \( X_a'\)
Bob needs to provide Alice with the following:
- Script public key: \( K_{Sb}\)
- Tari public key \( X_b'\)
Using the above equations in (7), Alice and Bob can calculate \(X\), \(X_a\), \(X_b\)
Minotari payment
Alice will construct the Minotari UTXO with the correct script and publish the containing transaction to the blockchain, knowing that she can reclaim her Minotari if Bob vanishes or tries to break the agreement. This is done with standard Mimblewimble rules and signatures.
Tari payment
When Bob sees that the Minotari UTXO that Alice created is mined on the Minotari blockchain with the correct script, Bob can publish the Tari transaction containing the Tari commitment with the aggregate key \(X = X_a + X_b + k_i \cdot G \).
Claim Minotari
When Alice sees that the Tari commitment that Bob created is confirmed on the second layer containing the correct aggregate
key \(X\), she can provide Bob with the required pre_image
to spend the Minotari UTXO. She does not have the
missing key \(x_b \) to claim the Tari yet, but it will be revealed when Bob claims the Minotari.
Bob can now supply the pre_image
and his Tari private key as transaction input to unlock the script.
Claim Tari
Alice can now see that Bob spent the Minotari UTXO, and by examining the input_data
required to satisfy the script, she
can learn Bob's secret Tari key. Although this private key \( x_b \) is now public knowledge, her part of the Tari spend key
is still private, and thus only she knows the complete Tari spend key. She can use this knowledge to claim the Tari commitment.
The refund
If something goes wrong and Bob never publishes the Tari or disappears, Alice needs to wait for the lock height
height_1
to pass. This will allow her to reclaim her Minotari, but in doing so, she needs to publish her Tari secret key
as input to the script to unlock the Minotari. When Bob comes back online, he can use this public knowledge to reclaim his
Tari, as only he knows both parts of the Tari commitment spend key.
The lapse transaction
If something goes wrong and Alice never gives Bob the required pre_image
, Bob needs to wait for the lock height
height_2
to pass. This will allow him to claim the Minotari he wanted all along, but in doing so, he needs to publish
his Tari secret key as input to the script to unlock the Minotari. When Alice comes back online, she can use this public
knowledge to claim the Tari she wanted all along as only she now knows both parts of the Tari commitment spend key.
Notation
Where possible, the "usual" notation is used to denote terms commonly found in cryptocurrency literature. Lower case characters are used as private keys, while uppercase characters are used as public keys. New terms introduced here are assigned greek lowercase letters in most cases. Some terms used here are noted down in TariScript.
Name | Symbol | Definition |
---|---|---|
subscript s | \( _s \) | The swap transaction |
subscript r | \( _r \) | The refund transaction |
subscript l | \( _l \) | The lapse transaction |
subscript a | \( _a \) | Belongs to Alice |
subscript b | \( _b \) | Belongs to Bob |
Tari key | \( X \) | Aggregate Tari public key |
Alice's Tari key | \( X_a \) | Alice's partial Tari public key |
Bob's Tari key | \( X_b \) | Bob's partial Tari public key |
Script key | \( K_s \) | The script key of the utxo |
Alice's Script key | \( K_sa \) | Alice's partial script key |
Bob's Script key | \( K_sb \) | Bob's partial script key |
Alice's adaptor signature | \( b'_{Sa} \) | Alice's adaptor signature for the signature \( b_{Sa} \) of the script_signature of the utxo |
Bob's adaptor signature | \( b'_{Sb} \) | Bob's adaptor signature for the \( b_{Sb} \) of the script_signature of the utxo |
Ristretto G generator | \(k \cdot G \) | Value k over Curve25519 G generator encoded with Ristretto |
Change Log
Date | Change | Author |
---|---|---|
23 Oct 2023 | Thaum -> Tari | CjS77 |
15 Nov 2022 | First outline | SWvHeerden |