A footprint-minimal coinswap protocol. Alice gives a coin to the Server, provided the Server gives a coin to Bob. There is no trust involved. Because all swaps go through the Server and the timelock eventually expires in their favor, a large number of swaps can be aggregated in a single UTXO that is efficiently on-chain redeemable by them. This comes at the cost of not being able to instantly access their funds, meaning the Server ends up locking up a substantial amount of coins.
All transactions that are involved with A
sending to B
Alice (A
) holds coins with Server (S
) that she can trustlessly redeem
On-chain UTXO_1 looks as follows:
A+S || S in 1 month
A
has an off-chain REDEEM_TX (signed by S) that spends from UTXO_1 with the following output:
A+S || A in 1 month
Now A
wants to send her coins to Bob (B
)
S
promises to fund and create new on-chain UTXO_2 that will look as follows:
B+S || S in 1 month
B
receives an off-chain REDEEM_TX (signed by S) that spends from UTXO_2 with the following output:
B+S || B in 1 month
If UTXO_2 appears on-chain, B
will be paid.
A
wants to forfeit her claim on UTXO_1 (i.e. A
to S
) provided UTXO_2 appears on-chain (i.e. S
to B
)
In order to achieve this, A
signs the following FORFEIT_TX that spends her REDEEM_TX:
S if UTXO_2 exists* || A in 1 month
*This kind of script is not possible today but is easier to explain, actual non-softfork version explained later
The effect is that S
can claim the funds from UTXO_1
if UTXO_2
is published.
Ideal/expected outcome:
S
publishes UTXO_2, meaningB
got paidA
won't publish her REDEEM_TX- The timelock on UTXO_1 expires and
S
claims the funds (timelock could be circumvented ifA
releases her privkey)
Outcome adversarial A
:
S
publishes UTXO_2, meaningB
got paidA
publishes her REDEEM_TXS
publishes the corresponding FORFEIT_TX and claims the funds
Outcome adversarial S
:
S
never publishes UTXO_2, soB
did NOT get paidA
publishes her REDEEM_TXS
publishes the corresponding FORFEIT_TX- The FORFEIT_TX timelock expires and
A
claims the funds
Outcome offline A
:
A
fails to askS
to transfer the funds toB
A
fails to publish her REDEEM_TX in time- The timelock on UTXO_1 expires and
S
claimsA
's funds
The protocol that was described thus far isn't any more efficient than A
simply sending an on-chain payment to B
. The final trick is that a single UTXO can contain coins for multiple users.
UTXO_1 is being shared here by two users and is eventually fully claimable by S
For instance, let's say A
and B
both had coins in the same pool as illustrated above. UTXO 1 would then be A+B+S || S in 1 month and this would branch off in a tree to two off-chain UTXOs with A+S || S in 1 month and B+S || S in 1 month. If both A
and B
forfeit their claim as expected, the off-chain UTXOs will never go on-chain. This works with any number of users and is what makes the protocol efficient.
Creating this transaction structure currently requires A+B+S to pre-sign, meaning all recipients have to interact with each other whenever a new UTXO is being created. OP_CTV would remove that requirement (update: this scheme similarly reduces interactivity without requiring CTV).
A single user might publish a REDEEM_TX. That single user will have to pay the fees to expand the tree of off-chain transactions and reach their specific output. This is costly to that user and thus puts a economic limit on what the smallest viable denomination inside Ark could be.
Also, since the tree got expanded, S
now has to spend log(n) outputs instead of 1 in order to claim the funds.
Instead of swapping for a new off-chain REDEEM_TX with S
, it is also simply possible to swap for an on-chain output without any timelocks, allowing for an optimally efficient exit.
The transaction that contains UTXO_2 could contain another small ANCHOR_OUTPUT that can only be spent by S
. A
can then include it as an input to her FORFEIT_TX to S
. Now the FORFEIT_TX can't be sent on-chain unless the transaction containing UTXO_2 as well as the ANCHOR_OUTPUT go on-chain first, thus fulfilling the "if UTXO_2 exists" condition.
The ANCHOR_OUTPUT can be kept off-chain by placing it inside an off-chain tree of transactions, though this does mean S has to expand the tree if it ever needed the anchor.
The main upside is the simplified interaction and no messy issues with eviction - spending coins doesn't require you to interact with all the people in the pool, just S
.
The main downside is reduced liquidity - the coins the Server receives back won't be available to them immediately, so the faster coins move hands, the more of S
's liquidity becomes locked up. If we assume a locktime of 30 days and on average 1BTC moving hands every 10 minutes, then S
will end up having 6 * 24 hours * 30 days = 4320BTC locked up.
A transfer isn't complete until the relevant UTXO confirms on-chain. However, if the recipient is willing to trust S
never to change transactions that are waiting to be confirmed, transfers could be subjectively viewed as instant.
The aim of this write-up was to concisely explain the core concepts behind Ark, as the original documentation has been difficult for many (myself included) to comprehend. Full accuracy was not the goal - and a lot of it was educated guess work / reverse engineering - so the actual Ark design will perhaps differ somewhat (though hopefully not massively) from what is written here.
(This explanation assumes you've read my Ark write-up)
Reducing Ark Interactivity Without Soft Fork
Currently both senders and recipients need to be online simultaneously to transfer value in Ark. This requirement can be reduced by a soft fork (i.e. OP_CTV). We can eliminate the need for a soft fork by giving both the sender and the recipient the option to complete a swap with
S
, allowing the recipient to complete the payment on their own. This method preserves proof of payment and has no race conditions.Let's say
A
wants to send toB
.A
getsS
to sign a newREDEEM_TX_AB
with the following script:B+S or A+S or A in 1 month
(i.e. adding theB+S
condition). We ensure the newREDEEM_TX_AB
becomes valid before the oldREDEEM_TX_A
with timelocks. NowA
foregoes her claim on the oldREDEEM_TX_A
by signing an unconditionalFORFEIT_TX
, thus allowingS
to simply claim the money ifREDEEM_TX_A
ever gets published.A
now sendsREDEEM_TX_AB
toB
, who can claim the payment by swapping withS
. IfB
isn't responsive,A
can perform the swap instead, or attempt to repeat the same steps with another recipient (note each attempt decrements the timelock - this could be mitigated as well but probably isn't needed).Proof of payment can be obtained from
S
onceB
performs a swap. IfS
maliciously refuses to cooperate (i.e. neither shows a proof of payment or performs a swap),A
can forceS
's hand by publishingREDEEM_TX_AB
, forcingS
to reveal whetherB
has swapped (i.e. ifB
signed aFORFEIT_TX
).