Subject: Re: [bitcoin-dev] Design for a CoinSwap implementation for massively improving Bitcoin privacy and fungibility

From: Chris Belcher <[email-masked]>
Date: Fri, 5 Jun 2020 23:39:47 +0100

Good day ZmnSCPxj,

>>> But S6 has the mild advantage that all the funding transactions paying to 2-of-2s can appear on the same block, whereas chaining swaps will have a particular order of when the transactions appear onchain, which might be used to derive the order of swaps.
>>
>> On the other hand, funds claiming in S6 is also ordered in time, so
>> someone paying attention to the mempool could guess as well the order of
>> swaps.
>>
>> I think this is wrong, and that it's possible for the funding
>> transactions of chained/routed swaps to all be in the same block as well.
>>
>> In CoinSwap it's possible to get DOS'd without the other side spending
>> money if you broadcast your funding transaction first and the other side
>> simply disappears. You'd get your money back but you have to waste time
>> and spend miner fees. The other side didn't spend money to do this, not
>> even miner fees.
>>
>> From the point of view of us as a maker in the route, we know we won't
>> get DOS'd like this for free if we only broadcast our funding
>> transaction once we've seen the other side's funding transaction being
>> broadcast first. This should work as long as the two transactions have a
>> similar fee rate. There might be an attack involving hash power: If the
>> other side has a small amount of hash power and mines only their funding
>> transaction in a manner similar to a finney attack, then our funding
>> transaction should get mined very soon afterwards by another miner and
>> the protocol will continue as normal. If the other side has knowledge of
>> the preimage and uses it to do CPFP and take the money, then we can
>> learn that preimage and do our own CPFP to get our money back too.
> 
> How about RBF?
> 
> A taker Alice can broadcast the funding tx spending its own funds.
> The funding tx spends funds controlled unilaterally by Alice.
> Alice can sign a replacement transaction for those funds, spending them to an address with unilateral control, and making the funding tx output with all the obligations attached never get confirmed in the first place.
> 
> The chances may be small --- Bob can certainly monitor for Alice broadcasting a replacement and counter-broadcast its own replacement --- but the risk still exists.
> TANSTAAGM (There Aint No Such Thing As A Global Mempool) also means Alice could arrange the replacement by other means, such as not using the RBF-enabled flag, broadcasting the self-paying replacement near miner nodes, and broadcasting the CoinSwap-expected funding tx near the Bob fullnode; Bob fullnode will then reject attempts to replace it, but miners will also reject the CoinSwap-expected funding tx and it will not confirm anyway.
> 
> 
> With the pre-SAS 4-tx setup, this potentially allows Alice to steal the funds of Bob; after Alice gets its funding-tx-replacement confirmed together with the Bob honest-funding-tx, Alice can use the contract transaction and publish the preimage to take the Bob funds.
> Since the Alice-side funding tx has been replaced, knowledge of the hash preimage will not help Bob any: the Alice funding tx has been replaced and Bob cannot use the preimage to claim it (it does not exist).
> 
> 
> With SAS Alice cannot outright steal the Bob funds, but the Bob funds will now be locked in a 2-of-2 and Alice can take it hostage (either Bob gives up on the funds, i.e. donates its value to all HODLers, or Bob gives most of the value to Alice).
> 
> 
> For the avoidance of theft, it is probably better for Bob to wait for Alice-side funding tx to confirm, probably deeply because reorgs suck.
> 
> This at least makes it costly to perform this attack; you have to lock more of your funds longer in order to induce a competitor to lock its funds.
> 
> 
> Come to think of it, the same issue probably holds for S6 as well, the funding tx with the longest timelock has to confirm first before the next is even broadcast, bleah.

Your RBF observation actually blows my idea out of the water. Not just
because of RBF but because of an attack by a miner.

Supposing that Alice starts with knowledge of the hash preimage, if she
uses RBF to make her funding transaction never confirm but allows Bob's
funding transaction to confirm, then Alice can use her preimage to take
the money from Bob's funding transaction. Bob will learn the value of
the preimage but it won't be much good to him because Alice's funding
transaction isn't valid anymore. Alice will get money from her funding
transaction and also money from Bob's funding transaction.

Because of this attack, it's pretty clear that a CoinSwap peer who
starts _without_ knowledge of the preimage must wait for the other
side's funding transaction to actually confirm, perhaps even with
multiple confirmations if they fear that the other side has access to
hashpower. For example, a miner could play the role of Alice and use
this attack to almost-risklessly steal Bob's coins using a finney attack.

That also seems to mean that a N-party routed CoinSwap requires at least
N blocks to be mined for all the funding transactions to be mined, which
is a slight setback for user experience. (Although even with today's
existing privacy tech, users must hang around waiting for coinjoins to
be signed, or waiting for multiple coinjoins to be confirmed.
Blockchains are inherently slow and we can't get around that.)

>>> For the avoidance of theft, it is probably better for Bob to wait for Alice-side funding tx to confirm, probably deeply because reorgs suck.
> 
> I realized that the *other* improvement I proposed in the [CoinSwapCS issue](https://github.com/AdamISZ/CoinSwapCS/issues/53) would help with this.
> Specifically, `nLockTime`-protected Backouts.
> 
> Suppose we have an S6 route as so, with Alice as taker and Bob1 and Bob2 as makers:
> 
>     Alice -> Bob1 -> Bob2 -> Alice
> 
> We assume here that Bob1 and Bob2 directly talk to Alice and that if Bob1 wants to talk to Bob2 it is done via Alice, so in the below if we say "Bob1 sends to Bob2" we imply that this is done via Alice.
> 
> 1.  Alice solicits fresh pubkeys from Bob1 and Bob2.
> 2.  Alice gives timeouts L1 and L2 to Bob1, and L2 and L3 to Bob2, such that L1 > L2 > L3, as well as negotiated amount, fees, etc.
> 3.  Alice creates (but does NOT sign) a funding tx paying to Alice && Bob1 and gives the txid to Bob1.
> 4.  Bob1 creates and signs a tx spending from the Alice funding tx and paying to Alice, with `nLockTime = L1`, and gives the signature to Alice.
> 5.  Bob1 creates (but does NOT sign) a funding tx paying to Bob1 && Bob2 and gives the txid to Bob2.
> 6.  Bob2 creates and signs a tx spending from the Bob1 funding tx and paying to Bob1, with `nLockTime = L2`, and gives the signature to Bob1.
> 7.  Bob2 creates (but does NOT sign) a funding tx paying to Bob2 && Alice and gives the txid to Alice.
> 8.  Alice creates and signs a tx spending from the Bob2 funding tx and paying to Bob2, with `nLockTime = L3`, and gives the signature to Bob2.
> 9.  Alice signals everyone to sign their respecting funding txes and broadcast them.
> 
> The rest of the CoinSwap protocol executes as normal once the funding txes are deeply confirmed.
> The only thing that Bob1 (resp. Bob2) needs to wait for is that the signatures for the incoming HTLC / PTLC have been received before forwarding to the next hop.
> This allows all funding txes to be confirmed in the same block, or even in some suitable random order (by having Alice send the signal out at different times/blocks to different makers).
> 
> The `nLockTime`d backout transactions are sufficient to allow everyone to recover their funds unilaterally in case one of the other funding txes do not confirm.
> 
> A similar technique can be done for SAS as well, but this removes the lack of encumbrance in the LTC-side output of SAS, which removes the advantage of having an otherwise unencumbered output.
> 
> In effect, the above creates Spilman unidirectional payment channels along the route, bringing the fiddly timing details offchain where it is less visible to observers.

I think I'm having trouble understanding this, does it work like this:

Say we're in the 2-party coinswap case (Alice and Bob)

We have Alice's funding transaction:
   Alice UTXO ---> 2of2 multisig (Alice+Bob)

And we have the regular contract transaction
   2of2 multisig (Alice+Bob) ---> Alice+timelock1 OR Bob+hashlock

And you propose a second pre-signed transaction?
   2of2 multisig (Alice+Bob) ---> Bob+timelock2

Where timelock2 > timelock1

If that's the protocol, then it's vulnerable to an attack. Once the
preimage is revealed we should be in a situation where Bob can
unilaterally get his coins back by broadcasting the regular contract
transaction and using the preimage to immediately get his coins. That
means Alice will be happy to hand over her private key, just to save
miner fees and improve privacy. But if the second pre-signed transaction
exists then Alice could do an attack where she broadcasts it and gets it
mined (perhaps more successfully if she has some hashpower). Once it's
mined then the regular contract transaction becomes invalid and Bob
can't get his money, in other words Bob doesn't have unilateral control
over those coins.