[bitcoin-dev] Detailed protocol design for routed multi-transaction CoinSwap

ZmnSCPxj ZmnSCPxj at protonmail.com
Thu Sep 3 09:45:53 UTC 2020

Good morning Chris,

> A big downside is that it really ruins the property of allowing coins to
> remain unspent indefinitely. That has privacy implications: if a coin
> remains unspent for longer than 2 weeks (or another short locktime) then
> for sure the transaction was not a CoinSwap, and so the anonymity set of
> the CoinSwap system would be far smaller For this reason I'm pretty
> desperate to solve the vulnerability without losing the coins remaining
> unspent indefinitely feature.

Ah, right.... accept no small privacy leaks!

> We need to solve the vulnerability you found, which I'll call the
> riskless theft attempt problem. So what do you think of this solution:
> == Building block 1: A, B and C having different contract txes ==
> In the original proposal each CoinSwap peer has the same contract
> transaction, and either side can broadcast it whenever they like. This
> actually isn't necessary. We can have a contract transaction
> fully-signed but only known to one peer, with a possibly-different
> transaction transaction fully-signed and only known to the other peer.
> Obviously for the CoinSwap to work both contract transactions must have
> the same hash-time-locked contract, but they can differ in other ways.
> == Building block 2: collateral payments ==
> The riskless theft attempt problem happens because the previous owner of
> the coins knows the fully-signed contract transaction and can broadcast
> it at no cost to themselves. So to solve the problem we add a cost.
> There is a 2of2 multisig made up of Bob's and Charlie's keys. The
> associated contract transaction known to Bob must now also have one of
> Bob's single-sig inputs. The outputs are such that some of the money
> from Bob's input now ends up in the HTLC output. The result is that
> after the CoinSwap if Bob broadcasts his contract transaction but fails
> to take the money from the HTLC output, then Bob will have lost money.

Just to be clear:

* B is the one who originally funded the HTLC, and owns the timelock.
* C is the one who will accept the HTLC, and owns the hashlock.

> I'm calling this idea collateral payments, by analogy with collateral
> used for loans. A collateral is someone valuable a debtor puts on the
> table, and if they don't repay the loan then they lose the collateral
> (presumably the creditor sells it to repay the loan).
> Here is a diagram of the contract transaction known to Bob:
> multisig (B+C) [I btc]---> (B+timelock_B OR C+hash) [I+K-M~ btc]
>     collateral(B)  [J btc]     (Bob)                    [J-K btc]
> where:
> I = CoinSwap amount
> J = Value of Bob's collateral input
> K = Value that Bob loses if he broadcasts his contract tx but doesnt
> get the money
> M~ = miner fee (random variable)
> The value K is something that can be set by the protocol, and made high
> enough so that doing a riskless theft attempt is not worth it. Probably
> the value of K will be quite small because the odds of a riskless
> payment attempt succeeding is very small (assuming the makers all use
> multiple redundant watchtowers). Mostly likely K will be smaller than
> M~, so if the collateral is lost to Bob then the miners will the ones to
> gain, rather than Charlie.

This seems a great solution!

Since B is the one offering HTLCs, the taker of a CoinSwap sequence can be B as well.
This means, the taker has to have *some* collateral input, of at least value K, that it cannot swap (because if it tried to swap that amount, it would be unable to provide a collateral as well).

How much does C need to know about the B collateralized contract transaction?
At the minimum, it has to know the output pays out to the correct contract, so it seems to me it has to know the entire B collateralized contract transaction, meaning it learns another input of B ("collateral(B)") that is not otherwise involved in the CoinSwap.
This is important, again, if B is a taker, as it means an unrelated input of B is now learned by C as having the same ownership as B.

A fresh maker that is given its starting funds in a single UTXO needs to split up its funds to make at least one collateral input it can use.

Of note is that the B output also serves as a point for CPFPing this transaction, thus only one version of the B collateralized contract transaction needs to be made, and the B collateralized contract transaction can be at or close to the minimum relay feerate and later CPFPed.

In terms of onchain analysis heuristics, it looks like the B output is change, while the B+C contract output is the send-out, I think, for most cases.
In case of a protocol abort, this heuristic is misled, since both outputs become owned by B due to the protocol abort.
In case of a protocol completion, this heuristic is accurate, since the B+C contract output will be claimed by C, but we do not expect this transaction to be confirmed onchain after protocol completion anyway (it effectively donates K to C or miners), so this is fine.

> The other contract transaction, known only to Charlie, does not contain
> a collateral input or collateral value (K), because Charlie can't do a
> riskless theft attempt to Bob.

Because it has a single output only, the C contract transaction needs to have RBFed versions.

> If Bob ever spends his collateral input in another transaction, then his
> contract transaction will become invalid. However Bob will only be
> harming himself, so he'll never do this.

At least until B gets its own incoming funds in the swap, at which point the collateral input can be used for other purposes (and effectively "releases" the lease of B on that output).

Since C knows the collateral input (it has to, in order to verify the B collateralized contract transaction is correct), it can monitor the collateral input for spendedness, and stop watching for the B collateralized contract transaction in its watchtower(s) if the collateral input is deeply spent.
The B collateralized contract transaction is invalidated if the collateral input is spent, and then only C can spend the funding outpoint at that point, so it can remove that from the watchtower.
This can be significant if C is using a for-pay watchtower that supports deletion of watches, which I believe is planned for watchtowers as well, and reduces the operating cost of C.


More information about the bitcoin-dev mailing list