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

Chris Belcher belcher at riseup.net
Fri Aug 21 09:47:31 UTC 2020


Hello,

On 21/08/2020 05:20, ZmnSCPxj wrote:
> Good morning,
> 
> 
> 
>> Right, so if the taker uses only a single maker then they must have more
>> than one UTXO.
> 
> Spending one UTXO is fine, it is generating a transaction that has one output that is problematic.
> 
> What needs to happen is that this single UTXO is spent to two outputs: the CoinSwap 2-of-2 and the change output.
> This is because intermediate makers will have very high likelihood of generating such a pattern (it is unlikely they have an exact amount that a taker would require of them), and the occassional maker might have a very large UTXO that it can use for similar purposes.
> 
> One thing a taker can do would be to multipath its CoinSwap, i.e. it spends any number of UTXOs and creates two outputs, which are actually two separate CoinSwap 2-of-2s to different makers.
> As each maker is unaware of the other, this should be similar to the case where the maker is an intermediate hop and is getting its incoming HTLC from another maker, which is unlikely to have a precise amount and will thus have a transaction that has two outputs, the 2-of-2 CoinSwap and the change.

Agreed.
I write about multipath CoinSwap routes in the original design document,
under "Combining multi-transaction with routing"


>>>> === Miner fees ===
>>>> Makers have no incentive to pay any miner fees. They only do
>>>> transactions which earn them an income and are willing to wait a very
>>>> long time for that to happen. By contrast takers want to create
>>>> transactions far more urgently. In JoinMarket we coded a protocol where
>>>> the maker could contribute to miner fees, but the market price offered
>>>> of that trended towards zero. So the reality is that takers will pay all
>>>> the miner fees. Also because makers don't know the taker's time
>>>> preference they don't know how much they should pay in miner fees.
>>>> The taker will have to set limits on how large the maker's transactions
>>>> are, otherwise makers could abuse this by having the taker consolidate
>>>> maker's UTXOs for free.
>>>
>>> Why not have the taker pay for the first maker-spent UTXO and have additional maker-spent UTXOs paid for by the maker?
>>> i.e. the taker indicates "swap me 1 BTC in 3 bags of 0.3, 0.3, and 0.4 BTC", and pays for one UTXO spent for each "bag" (thus pays for 3 UTXOs).
>>> Disagreements on feerate can be resolved by having the taker set the feerate, i.e. "the customer is always right".
>>> Thus if the maker has to spend two UTXOs to make up the 0.4 BTC bag, it pays for the mining fees for that extra UTXO.
>>> The maker can always reject the swap attempt if it has to spend multiple UTXOs and would lose money doing so if the taker demands a too-high feerate.
>>
>> Having the taker pay for just one UTXO will have an unfortunate side
>> effect of resulting in the maker's money being split up into a large
>> number of UTXOs, because every CoinSwap they take part in has an
>> incentive to increase their UTXO count by one. At the start of
>> JoinMarket this was an issue where then a taker wanting to CoinJoin a
>> large would come along and the result would be a huge CoinJoin
>> transaction with many many small inputs. Perhaps the taker could pay for
>> 2-3 UTXOs to counteract this. (Of course the exact number would be
>> configurable by the taker user, but defaults usually don't get changed).
>>
>> I'm still not convinced with having makers contribute to miner fees. In
>> JoinMarket we tried to get makers to contribute a little to miner fees
>> and simply they never did in any meaningful way. The market has spoken.
>> In terms of incentives makers are happy to wait a very long time, if we
>> assume they're just HODLers then even if they earn a few thousand
>> satoshis that's good.
>>
>>>> == Contract transaction definitions ==
>>>> Contract transactions are those which may spend from the 2-of-2 multisig
>>>> outputs, they transfer the coins into a contract where the coins can be
>>>> spent either by waiting for a timeout or providing a hash preimage
>>>> value. Ideally contract transactions will never be broadcast but their
>>>> existence keeps all parties honest.
>>>> M~ is miner fees, which we treat as a random variable, and ultimately
>>>> set by whichever pre-signed RBF tx get mined. When we talk about the
>>>> contract tx, we actually mean perhaps 20-30 transactions which only
>>>> differ by the miner fee and have RBF enabled, so they can be broadcasted
>>>> in sequence to get the contract transaction mined regardless of the
>>>> demand for block space.
>>>
>>> The highest-fee version could have, in addition, CPFP-anchor outputs, like those being proposed in Lightning, so even if onchain fees rise above the largest fee reservation, it is possible to add even more fees.
>>> Or not.
>>> Hmm.
>>
>> I think RBF transactions are better because they ultimately use less
>> block space than CPFP.
>>
>> There seems to be very little cost in signing many additional
>> precomputed RBF transactions. So the taker and makers could sign
>> transactions all the way up to 10000 sat/vbyte. I think this doesn't
>> apply to Lightning, because bandwidth seems to be more constrained
>> there: even a tiny micropayment for 1 satoshi would require 10x or 100x
>> more bandwidth if every lightning htlc used precomputed RBF.
> 
> I was wondering if it would be a good idea actually if the **largest** fee RBF transaction had additional CPFP anchor outputs, not saying to replace the entire group of RBF transactions entirely.
> 
> This is just in case of a very sudden increase in feerates that goes beyond the largest that was prepared beforehand.
> "You cannot predict the feerates future" is becoming something of a mantra over in Lightning, though I guess a "big enough" spread of RBF transactions would work in practice >99% of the time.

Got it. I agree having a CPFP anchor output on the largest fee RBF is a
good idea then.

> 
>>>> (Alice+timelock_A OR Bob+hash) = Is an output which can be spent
>>>> either with Alice's private key
>>>> after waiting for a relative
>>>> timelock_A, or by Bob's private key by
>>>> revealing a hash preimage value
>>>
>>> The rationale for relative timelocks is that it makes private key turnover slightly more useable by ensuring that, after private key turnover, it is possible to wait indefinitely to spend the UTXO it received.
>>> This is in contrast with absolute timelocks, where after private key turnover, it is required to spend received UTXO before the absolute timeout.
>>> The dangers are:
>>>
>>> -   Until it receives the private key, if either of the incoming or outgoing contract transactions are confirmed, every swap participant (taker or maker) should also broadcast the other contract transaction, and resolve by onchain transactions (with loss of privacy).
>>> -   After receiving the private key, if the incoming contract transaction is confirmed, it should spend the resulting contract output.
>>> -   It is possible to steal from a participant if that participant goes offline longer than the timeout.
>>>     This may imply that there may have to be some minimum timeout that makers indicate in their advertisements.
>>>     -   The taker can detect if the first maker is offline, then if it is offline, try a contract transaction broadcast, if it confirms, the taker can wait for the timeout; if it times out, the taker can clawback the transaction.
>>>         -   This appears to be riskless for the taker.
>>>         -   Against a similar attack, Lightning requires channel reserves, which means the first hop never gains control of the entire value, which is a basic requirement for private key turnover.
>>>     -   On the other hand, the taker has the largest timeout before it can clawback the funds, so it would wait for a long time, and at any time in between the first maker can come online and spend using the hashlock branch.
>>>         -   But the taker can just try on the hope it works; it has nothing to lose.
>>>     -   This attack seems to be possible only for the taker to mount.
>>>         Other makers on the route cannot know who the other makers are, without cooperation of the taker, who is the only one who knows all the makers.
>>>         -   On the other hand, the last maker in the route has an outgoing HTLC with the smallest timelock, so it is the least-risk and therefore a maker who notices its outgoing HTLC has a low timeout might want to just do this anyway even if it is unsure if the taker is offline.
>>
>> Every off-chain protocol like this has the livelyness requirement. Each
>> party must always be watching the chain and be ready to broadcast
>> something in response. I'm not sure how any of this relates to the
>> choice of relative vs absolute time locks.
> 
> Absolute timelocks mean that you can set a timer where you put your node to sleep without risk of loss of funds (basically, once the absolute timelocks have resolved, you can forget about CoinSwaps).
> But I think the ability to spend at any time would be better, and getting 100% online 144 blocks a day, 2016 blocks a retargeting period is becoming more and more feasible.

You can always put your node to sleep as a maker, and your watchtowers
will protect you.

What do you mean by the point about 100% online nodes getting more
feasible? Many bitcoin nodes have been always-on for years, I think I
missed something.

>> You're right that attempting such an move by the taker is riskless, but
>> its not costless. The taker sets up the entire CoinSwap protocol because
>> they wanted more privacy; but if the taker broadcasts the Alice contract
>> transaction and waits for the timeout, then all they've achieved is
>> spent miner fees, got their own coin back and draw attention to it with
>> the unusual HTLC script. They've achieved no benefit from what I see, so
>> they won't do this. Any taker or maker who attempts anything like this
>> will be spending miner fees.
> 
> They would be spending miner fees *from the funds being stolen*, thus still costless.
> 
> In particular, let us imagine a simple 1-maker swap.
> 
> * The taker and the maker complete the swap.
> * The taker now has possession of:
>   * The private key for its incoming HTLC.
>   * The pre-signed contract transaction for its outgoing HTLC.
> * The taker spends from its incoming HTLC using the private key.
>   * The maker ignores this, because this is just normal operation.
>   * Fees paid for this is not an **additional** cost, because a taker that wants to put its freshly-private funds into cold storage will do this anyway.
>   * The taker gets a fresh, private coin from this incoming HTLC, so it gets the privacy it paid for.
> * The taker waits for the incoming-HTLC-spend to confirm.
> * The taker broadcasts the pre-signed contract transaction, in the hope that the maker is offline.
>   * The fees paid for this are from the contract transaction that the taker is trying to steal.
>     Even if the theft attempt fails, the taker has already gotten its private money out, and is thus not risking anything.
>   * Semantically, the outgoing HTLC is already "owned" by the maker (the maker has private key to it).
>     * Thus, the taker commits an action that the maker pays fees for!
>   * The maker cannot react except to spend via the hashlock branch.
>     In particular, because the taker-incoming (maker-outgoing) UTXO is already spent, it cannot retaliate by also broadcasting the contract transaction of the taker-incoming (maker-outgoing) HTLC.
> * The theft succeeds (the timelock passes) because the maker happens to be offline for that long.
>   * This is "free money" to the taker, who has already gotten what it paid for --- private money in cold storage --- from the CoinSwap.
>   * Even if the stolen fund reveals the contract, the taker can re-acquire privacy for the funds it stole for free, by paying for --- wait for it --- another CoinSwap for its swag.

Yep you're right, I get it.

The biggest defense against theft will have to be multiple redundant
watchtowers. But as you say the attack is riskless and costless for the
taker to attempt, so they might try anyway even if the probability of
success is very low.

If this attack becomes widespread then it effectively breaks the
property that maker's coins remain unspent indefinitely. It seems like
that would lead to makers increasing their CoinSwap fees because they
know they'll always have to spend a bit of miner fees afterwards.

Hopefully the success rate for this attack can be low enough that
taker's human niceness will stop them trying. But for sure this is a
concerning problem.

> Using an absolute timelock (implemented by a `nLockTime` tx directly off the 2-of-2, ***not*** `OP_CHECKLOCKTIMEVERIFY`), plus a Scriptless Script 2p-ECDSA (again implemented by a tx directly off the 2-of-2) instead of a hashlock, seems to avoid this, I think, at the cost of reducing the utility of private key turnover by having a deadline where the private key *has to* be used.
> This is because there is no contract transaction that is share-owned by both participants in the swap.
> Instead there are two distinct transactions with separate ownerships: a timeout tx (that is owned by the participant paying for the HTLC/PTLC) and a claim tx (that is owned by the participant accepting the HTLC/PTLC).

A downside of using absolute timelocks is that it combines the two time
periods: the time period where a watchtower must respond and the time
period under which private keys must be used.

So for example if the absolute timelock is set to 3 weeks, that means
the maker has 3 weeks to spend their coins using the private keys which
is a nice long period. However if the CoinSwaps fails with the timeout
case then the maker has to wait 3 weeks to get their coins back, which
is a long time.

We can go the other extreme and set the absolute timelock to be 2 days.
Then the maker only has to wait 2 days in the unfortunate event that
their coinswap fails with the timeout case. But it means they must use
their private keys to spend coins within the short period of 2 days(!)

Though this still might be worth it to solve the riskless/costless
stealing attempts.


>>> -   Participants might want to spend from the UTXO to a new address after private key turnover anyway.
>>>     Makers could spend using a low-fee RBF-enabled tx, and when another request comes in for another swap, try to build a new funding tx with a higher-fee bump.
>>>
>>
>> I don't think this will happen very often. It's spending money on block
>> space for not much benefit. If the maker ever decides to shut down their
>> maker they can transfer all their coins in HTLCs to single-sig
>> transactions exclusively controlled by them, but in normal operation I
>> doubt it will happen.
> 
> Accidents can happen (e.g. somebody trips over the power cord of the maker hardware), so hedging this somewhat might give a useful safety net.

Right, but taking out the maker hardware isn't enough for funds to be
stolen, all the watchtowers would need to be taken out too.


>>>> == EC tweak to reduce one round trip ==
>>>> When two parties are agreeing on a 2-of-2 multisig address, they need to
>>>> agree on their public keys. We can avoid one round trip by using the EC
>>>> tweak trick.
>>>> When Alice, the taker, downloads the entire offer book for the liquidity
>>>> market, the offers will also contain a EC public key. Alice can tweak
>>>> this to generate a brand new public key for which the maker knows the
>>>> private key. This public key will be one of the keys in the 2-of-2
>>>> multisig. This feature removes one round trip from the protocol.
>>>> q = EC privkey generated by maker
>>>> Q = q.G = EC pubkey published by maker
>>>> p = nonce generated by taker
>>>> P = p.G = nonce point calculated by taker
>>>> R = Q + P = pubkey used in bitcoin transaction
>>>> = (q + p).G
>>>
>>> Whoa whoa whoa whoa.
>>> All this time I was thinking you were going to use 2p-ECDSA for all 2-of-2s.
>>> In which case, the private key generated by the taker would be sufficient tweak to blind this.
>>> In 2p-ECDSA, for two participants M = m * G; T = t * G, the total key is m * t * G = m * T = t * M.
>>> Are you going to use `2 <T> <Q+P> 2 OP_CHECKMULTISIG` instead of 2p-ECDSA?
>>> Note that you cannot usefully hide among Lightning mutual closes, because of the reserve; Lightning mutual closes are very very likely to be spent in a 1-input (that spends from a 2-of-2 P2WSH), 2-output (that pays to two P2WPKHs) tx.
>>
>> Yes, I intend for 2p-ECDSA to be used eventually, but for the first
>> version I'll only implement regular multisigs with OP_CHECKMULTISIG.
>> Once all the other details of this protocol are implemented correctly
>> and mostly-bug-free then 2p-ECDSA can be added. It can be added in the
>> protocol steps 0-1, 3-5 and 7-9.
> 
> Okay, that is clearer.
> 
> I think 2p-ECDSA should be first priority after getting a decent alpha version.
> 
>> This document also doesn't talk about PayJoin-with-CoinSwap, but that
>> can be added later too.
> 
> 2p-ECDSA with Scriptless Script potentially gives a lot more privacy than any PayJoin IMO, due simply to the much larger anonymity set, and there are enough chain-analysis-heuristic-breaking shenanigans we can implement with plain CoinSwap, I think.

I completely agree.


Regards
CB


More information about the bitcoin-dev mailing list