Taprootized Atomic Swaps (TAS) is an extension for Atomic Swaps that presumes the untraceability of transactions related to a particular swap. Based on Schnorr signatures, Taproot technology, and zero-knowledge proofs, the taprootized atomic swaps hide swap transactions under regular payments.
Atomic swap is an incredible approach to cross-chain exchanges without mediators. However, one of the disadvantages of its implementation in the classical form is the “digital trail” — any party can make a matching between transactions in the blockchains in which the exchange took place and find out both the participants in the exchange and the proportion in which assets were exchanged.
On the other hand, atomic swaps is a technology that initially assumed the involvement of only two parties and a “mathematical contract” between them directly. That is, an ideal exchange presupposes 2 conditions:
- Only counterparties participate in the exchange (works by default)
- Only counterparties know about the fact of the exchange (it would be nice to ensure)
This paper will provide a concept of taprootized atomic swaps that allow hiding the swap's very fact. To an external auditor, transactions to initiate and execute atomic swaps will be indistinguishable from regular Bitcoin payments. In the other accounting system involved in the transfer, more information is disclosed (the fact of exchange can be traced). Still, it is impossible to link this to the corresponding Bitcoin transactions (without additional context from the involved parties).
- Alice (
skA
,PKA
) and Bob (skB
,PKB
) have their keypairs and know each other's public keys. - Alice generates a random
k
and calculates the public valueK = k * G
- Alice forms the alternative spending path
Script = sig(skA) + Locktime
in the form of Bitcoin Script - Alice calculates an escrow public key as
PKEsc = K + PKB + hash((K + PKB) || Script) * G
(here, escrow is just a public key, formed using Taproot technology- The signature
sig(skEsc)
, verified by thrPKEsc
, can be generated only with the knowledge ofk
,skB
andScript
- The signature
- Alice calculates the
h
as a hash value ofk
(zk-friendly hash function is recommended to use) - Alice forms the funding transactions with the following conditions of how it can be spent:
- Signature of
skEsc
: Bob, with knowledge ofk
andskB
can spend the output - Signature of
skA
+ Locktime: Alice, with knowledge ofskA
can spend the output, but only after some point in timet1
(it's theScript
itself)
- Signature of
- Alice sends the transaction to the Bitcoin network
- Alice generates the zero-knowledge
proof
that includes:- The proof of knowledge of
k
that satisfiesk * G == K
- The proof of knowledge of
k
that satisfieszkHash(k) == h
- The proof of knowledge of
- Alice provides the set of data to Bob:
h
K
Script
proof
- Bob calculates
PKEsc
asK + PKB + hash((K + PKB) || Script) * G
and finds the transaction locked BTC (verifies it exists). Then Bob performs the following verification:- Verifies that Alice knows
k
that satisfiesk*G == K
andzkHash(k) == h
, it means that Bob can access the outputPKEsc
if he receivesk
- Verifies that the
Script
is correct and includes only the required alternative path.
- Verifies that Alice knows
- If verifications are passed, Bob forms the transaction that locks his funds on the following conditions:
- Publishing of
k
and the signature ofskA
: only Alice can spend it if she revealsk
(hash preimage) - Signature of
skB
+ Locktime: Bob, with knowledge ofskB
, can spend the output, but only after some point in timet2
- Publishing of
- Bob sends the transaction to the Ethereum network (or any other that supports
zkHash()
) - Alice sees the locking conditions defined by Bob and publishes the
k
together with the signature generated by herskA
. As a result - Alice spent funds locked by Bob.- If Alice doesn’t publish the relevant
k
, Bob can return funds after locktime is reached
- If Alice doesn’t publish the relevant
- If Alice publishes a transaction with
k
, Bob can recognize it and extract thek
value - Bob calculate the needed
skEsc
asskEsc = k + skB + hash((K + PKB) || Script)
- Bob sends the transaction with the signature generated by the
skEsc
and spends funds locked by Alice.
Transactions:
- Alice locks BTC: 850e9258bf8b3bb280d32a647198d8024aece543dc283f7bfa526f4c0ceb1ab8
- Bob locks ETH: 723919c0e8ec57d38792ec29b2cb82ee885b9fbbc886b34ff40fb5d3f7cc9b43
- Alice withdraws ETH from the contract: 47546191a7c99ec4a7ddc243d6ea75d345ab3aff0762e09dd2f537731bd484f3
- Bob spends BTC: 859dbfaa901d7106aecc8cb29966ede0c9d7a17c2cae31f4d420c1d770e9706d
This repository provides all components for executing an atomic swap, including a script for an Ethereum-Bitcoin exchange between Alice and Bob.
circuits
: ContainsCircom
circuits for Zero-Knowledge proof creation in step eight of the outlined flow. These circuits verify the knowledge of a private 256-bit scalark
, whereK = k * G
andh = Poseidon(k)
, withK
andh
being public,Poseidon
being the hash function, andG
representing the Secp256k1 base point.contracts
: Contains theDepositor
contract in Solidity designed for depositing native currency using a 256-bit numberh
andlocktime
, locking funds with two withdrawal conditions:- Spender knows some
k
thath = Poseidon(k)
- money goes to the message sender locktime
has passed - money goes to the deposit maker
- Spender knows some
crates
: Contains Rust crates for ZkSnark witness, proof generation, and validation. Proof generation currently takes about 13 seconds on an M1 Pro chip, with witness calculation accounting for 10 seconds. Utilizingc++
bindings instead of the existingwasm
witness calculator can notably reduce this time.src
: Contains the Rust script for facilitating an atomic swap between Alice and Bob. It encompasses all steps outlined in the documentation, including proof generation, taproot transaction creation, and executing transactions on both Bitcoin and Ethereum networks.scripts
: Contains auxiliary scripts for Circom and SnarkJS.
You can use either testnets for Ethereum and Bitcoin networks or run the local test networks by
using such utilities as ganache
for Ethereum and
nigiri
for Bitcoin.
You can use this deployed, verified and ready for use contracts:
- Ethereum mainnet:
0x936f971455bc674F77312f451963681fe964E838
- Sepolia testnet:
0x85BEaB7f80B375175BeCC3f68Bf86d33099fD576
You can use trusted setup files (.ptau
, at least 17th power) from [SnarkJs
] repository, you
can find it in the readme section, for ZK proof generation.
- Install
Cargo
,Circom
,SnarkJS
- Setup
config.toml
. Check the config.example.toml for example, it has detailed description. - Compile atomic-swap executable:
cargo install --path .
- Run the script with the config that is configured for section 2:
taprootized-atomic-swap config.toml
Before compiling make sure, that you have the OpenMP installed on your device. It is required
dependency to build the rapidsnark-sys
crate.
sudo apt update sudo apt upgrade
sudo apt install libomp-dev
We use a circom ecdsa implementation from 0xPARC.