Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DRAFT] Succinct Atomic Swaps
Browse files Browse the repository at this point in the history
GeneFerneau committed May 24, 2021
1 parent 709606d commit e2d2e6c
Showing 2 changed files with 175 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ To begin writing your own RFC or to find out more about the process and the gene
| [0019-deprecate-http-tx](text/0019-deprecate-http-tx.md) | ACTIVE | Deprecating HTTP(S) as a transaction method in grin-wallet. |
| [0020-pibd-messages](text/0020-pibd-messages.md) | ACTIVE | Define new peer-to-peer messages to enable a novel sync method, using packets of self-contained partial state that can be downloaded and verified independently from each other. |
| [0021-fix-prior-fees](text/0021-fix-prior-fees.md) | ACTIVE | Carry the restriction of fees, to 40 bits since HF4, back to all history. |
| [0000-succinct-atomic-swaps](text/0000-succinct-atomic-swaps.md) | DRAFT | Perform succinct atomic swaps between Grin and other cryptocurrencies. |

## License

174 changes: 174 additions & 0 deletions text/0000-succinct-atomic-swaps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@

- Title: succinct-atomic-swaps
- Author: [Gene Ferneau](mailto:gene@ferneau.link)
- Start date: March 21, 2021
- RFC PR: [tbd]()
- Tracking Issue: [tbd]()

---

# Summary
[summary]: #summary

Succinct atomic swaps [\[1\]](#references) are a technique developed by Ruben Somsen to atomically exchange funds between mutually untrusting parties using the Bitcoin cryptocurrency.
The techniques can be adapted to work for the Grin cryptocurrency following guides developed by Jasper van der Maarel [\[2\]](#references). A previous version of the protocol was implemented
using Hash-based Time Locked Contracts in the [grinswap](https://github.com/GrinSwap/proof-of-concept) wallet project.

# Motivation
[motivation]: #motivation

This RFC aims to show a succinct atomic swap protocol using adaptor signatures, accompanied by an implementation in the reference Mimblewimble wallet [grin-wallet](https://github.com/geneferneau/grin-wallet/tree/atomic). All Grin wallet implementations should be able to use this RFC to interoperate, and perform atomic swaps with each other.

# Community-level explanation
[community-level-explanation]: #community-level-explanation

In an atomic swap, two parties agree to lock funds on one chain (e.g. Bitcoin), and interactively unlock funds on another chain (e.g. Grin). By unlocking funds on the Grin chain, the secret to unlock the funds on the Bitcoin chain is revealed. Revealing the secret this way allows the exchange to happen "atomically": when one lock is opened, so is the other lock. This atomic structure keeps one party from being able to steal funds from the other party: either both locks are opened, or neither are opened.

The reference implementation uses Bitcoin as the other chain in the swap, but potentially any other chain using Secp256k1 keys and multisignatures can work with the protocol.

# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation

Funds on the non-Grin chain need to be locked in a multisignature transaction that requires knowledge of both "atomic nonces" to be spent. A refund transaction is also needed to recover funds in case one of the parties becomes non-responsive, or the protocol needs to be aborted for another reason.

## Atomic nonces
[atomic-nonces]: #atomic-nonces

In the case of Grin, atomic nonces are just Secp256k1 private keys used to unlock funds on the other chain. Let's say Alice knows atomic nonce `nA`, and Bob knows atomic nonce `nB`.

In the refund transaction, Alice (with locked Grin funds) will reveal her nonce `nA` to allow Bob to recover his locked funds on the other chain.

In the main transaction, Bob and Alice create a multisignature Grin transaction which reveals Bob's nonce `nB` to Alice. Alice can then recover the funds locked on the other chain.

Atomic IDs are identifiers used to derive atomic nonces using the keychain. Atomic IDs are formatted as follows:

```
0x4 | 'mwatomic' | 0x0 0x0 0x0 0x0 | 32-bit ID
```

The 32-bit ID can be expanded to 64-bits if necessary, and doesn't need to be random (it can be a simple counter). However, an ID can only be used once.

Currently, output blinding factors and signature nonces use the key ID of the inputs and outputs, which is derived from the current child key path, or next available key path.

Atomic swaps still use the default methods for deriving blinding factors and signature nonces. The atomic IDs are domain separated to help ensure they don't collide with normal blinding factors and signature nonces.

Atomic nonces must only be used **once**. Reuse potentially results in loss of funds, if the other party has the previously used nonce.

Without automated defenses, a malicious party could trick a user into deriving the same nonce (by supplying a duplicate atomic ID). The malicious user could then recover funds on the other chain without completing the atomic swap protocol.

Regular blinding factors and signature nonces use a strictly increasing counter to prevent deriving the same factors more than once. However, this technique alone won't work for atomic nonces. The atomic ID is shared between parties, meaning a malicious attacker could attempt to trick a user into reusing an atomic ID.

Currently, the automated defense is to use a space-efficient filter (`scalable cuckoo filter`), which is stored in the wallet's database. The filter cannot be reconstructed if the wallet file is deleted and recovered, so it is recommended to use a new keymask for any future atomic swaps.

## Adaptor signatures
[adaptor-signatures]: #adaptor-signatures

Adaptor signatures were originally invented by Andrew Poelstra [\[3\]](#references). Adaptor signatures use additive properties of Schnorr signatures to commit to a secret, then later reveal it by creating a full Schnorr signature over the same message.


## Protocol rounds
[protocol-rounds]: #protocol-rounds

In Grin, let `kB` be Bob's random kernel nonce, `rB` be Bob's random blinding factor, `nB` be Bob's atomic nonce. Let `kA` and `rA` be Alice's random kernel nonce and blinding factor.

Alice and Bob must perform an atomic swap refund transaction before the main transaction. After a Alice receives the slate in the fourth refund round, both parties can lock funds on the other chain.

An illustration of the protocol (credit @tromp + @RubenSomsen):

```
+----------+ +-------------+ 1 day +-------------+ 2 days +----------+
| 87k Grin | ---> | 87k Grin | -----> | 87k Grin | --------> | 87k Grin |
| Alice | | Alice + Bob | | Alice + Bob | reveals | Alice |
+----------+ +-------------+ +-------------+ secretA +----------+
| | 3
| | days
| v
|
| +----------+
+-------------> | 87k Grin |
reveals | Bob |
secretB +----------+
+-------+ +-------------------+
| 1 BTC | ----> | 1 BTC |
| Bob | | secretA + secretB |
+-------+ +-------------------+
```

The following is a description of the main transaction rounds.

1. `init_atomic_swap`

In the first round, Alice sends her public random kernel nonce and blinding factor (`kA*G` and `rA*G`) to Bob.

2. `receive_atomic_swap`

Bob creates an adaptor signature as follows (where `e` is the kernel message):

```
sr' = kB + nB + rB*e
```

Bob sends `sr'` as his partial signature, and public atomic nonce `nB*G` in the second round of the swap.

3. `countersign_atomic_swap`

Alice can verify the adaptor signature by supplying Bob's public atomic nonce to the Schnorr verification algorithm as an extra nonce (this capability exists in Grin's fork of `libsecp256k1`). Alice stores the `s` component (`s = sr'[32:]`) to recover the atomic nonce during swap finalization.

If the adaptor signature is valid, Alice computes her partial signature over the kernel message `e = SHA256(M | kB*G + kA*G)`, using `kA` and `rA` as her kernel nonce and blinding factor:

`ss = kA + rA*e`

4. `finalize_atomic_swap`

Bob verifies the partial signature, and if valid, creates his final signature:

`sr = kB + rB*e`

and adds it to Alice's partial signature:

`sr + ss = kA + kB + rA*e + rB*e`

Bob posts the transaction to the blockchain, and sends the final slate to Alice. The slate is used for Alice to recover her partial signature, which may be possible by encrypting the third round slate to both Bob and herself (TBD). Currently, in the tests Alice recovers her partial signature from the finalized slate. This is not ideal, since Bob can simply finalize/post the transaction, without sending the slate to Alice.

The refund transaction is much the same, with the roles reversed. Alice also holds the finalized refund transaction, unless she wants to abort the protocol.

The refund transaction also includes a timelock `lock_height`, to ensure the transaction isn't valid until a reasonable time after expected normal swap completion. This prevents a race where Bob could post the finalized main transaction (revealing his atomic nonce), and Alice could simultaneously post her refund transaction.

If the `lock_height` were not there, the miners could see the refund transaction first, and reject the main transaction as a double-spend. Alice could then potentially recover the funds on both chains.

## Nonce recovery
[nonce-recovery]: #nonce-recovery

With the kernel excess commitment, Alice can recover the transaction kernel after the transaction is posted to the blockchain. Alice can then use her partial signature, and the finalized kernel excess signature to recover Bob's partial signature.

Alice subtracts Bob's partial signature from his adaptor signature to recover his atomic nonce `nB`:

```
nB = sr' - sr
= (kB + nB + rB*e) - (kB + rB*e)
= nB + (kB - kB) + (rB*e - rB*e)
```

# Unresolved questions
[unresolved-questions]: #unresolved-questions

- Is there any way to reduce the amount of rounds required per atomic swap transaction (currently 4 rounds each, 8 total)?
- [scalable cuckoo filters](https://github.com/sile/scalable_cuckoo_filter) are used to locally ensure no nonce reuse, are vacuum filters [\[4\]](http://www.vldb.org/pvldb/vol13/p197-wang.pdf) a better replacement?

# Future possibilites

Ruben Somsen's protocol allows for a 2-transaction version, where only two on-chain transactions are posted. This means one Grin transaction, and one transaction on the other chain (e.g. Bitcoin). The 2-transaction protocol requires using watchtowers, and for the parties to be online for the duration of the swap. It may not be worth the additional complexity, considering it only saves one on-chain transaction, and Grin transactions are currently not that expensive. If Grin fees were ever to reach/exceed Bitcoin's, it may be worth reconsidering.

Somsen also has a variant using relative timelocks, which could be implemented on Grin using No Recent Duplicate kernels [\[5\]](#references). This would allow for a more automated way to post the refund transaction, but requires NRD kernel activation on mainnet.

# References
[references]: #references
- \[1\] [Succinct Atomic Swaps](https://gist.github.com/RubenSomsen/8853a66a64825716f51b409be528355f)
- \[2\] [Grin docs for Atomic Swaps](https://docs.grin.mw/wiki/transactions/contracts/#atomic-swap)
- \[3\] [Scriptless Scripts](https://download.wpsoftware.net/bitcoin/wizardry/mw-slides/2018-05-18-l2/slides.pdf)
- \[4\] [Vacuum Filters](https://www.vldb.org/pvldb/vol13/p197-wang.pdf)
- \[5\] [NRD Kernels](https://github.com/mimblewimble/grin-rfcs/blob/master/text/0013-nrd-kernels.md)

0 comments on commit e2d2e6c

Please sign in to comment.