Skip to content

Instantly share code, notes, and snippets.

@sickpig
Last active November 22, 2019 16:19
Show Gist options
  • Save sickpig/231fbde2839a889d67848180d65f17b0 to your computer and use it in GitHub Desktop.
Save sickpig/231fbde2839a889d67848180d65f17b0 to your computer and use it in GitHub Desktop.
Mitigating DS attacks leveraging delta in mempool admission policies

Mitigating of DS attacks leveraging delta in mempool admission policies

We are going to lay out how having BU accepting longer chain of unconfirmed transactions than ABC could be used to increase the chance of a double spend attack to be successful and how to mitigate it.

Definitions: DS and different kind of attack

First the definition of what a double spend (DS) or a respend is. Define a respend as an unconfirmed transaction that spends one or more UTXOs also spent by another unconfirmed transaction, which differs from it even when scriptSig contents are ignored1.

There are different kind of DS attacks that have been described in great detail along the last 2 years or so2. The following is a brief summary of the known attacks:

  1. fast respend is transmitted simultaneously or almost simultaneously with the legitimate transaction.
  2. reverse respend is a nonstandard respend transaction placed with miners before the legitimate tx is broadcast.
  3. High fee respend, i.e. miner bribing.

In this document we are going to focus on the first 2 kinds of attack which are those who applied to the situation at hand.

Attack scenario #1: fast respend.

A merchant run a BU node which accept chain of unconfirmed transactions longer than what ABC nodes used by miners (currently 25).

We suppose that all miners are running node that are not accepting chains of transactions longer than 25 in their mempools.

An evil customer will buy a coffee with a transaction (TX1) that spend an "unconfirmed" UTXO with 25 parents (A).

TX1 will be accepted only by BU nodes as the 26th transaction in the chain and rejected by ABC onces.

Merchant will probably accept to exchange the good after a few seconds that TX1 get broadcasted3.

The evil customer can't try a fast respend immediately using a new transaction (TX2) that spend A to a different recipient. This is due to the fact TX2 won't get accepted anyway in ABC nodes because it still spend an unconfirmed UTXO and more to the point it will probably trig a warning in the BU node4.

What the attacker have to do is to wait for a block that includes the 25 TX1 ancestors (or a subset of them) so that now any new TX that spend A become acceptable also by ABC nodes.

As soon as the block is found she broadcasts TX2 to the network, TX1 will try to spend A to a different address and hoping to win the race and get his coffee for free.

Attack scenario #1: a mitigation.

As of BU 1.7 bitcoind will forward TX1 only to nodes that are going to accept it (i.e other BU peers). It won't do it for any other nodes. This is possible because BU is aware of the mempool admission policies of other Bitcoin Cash nodes pertaining to unconfirmed transaction chain limits6, 7 .

Once TX1 becomes acceptable to a peer (if some of its parents are confirmed, for example) BU node will forward the transaction to that peer.

This mean that once the evil customer will broadcast TX2, she will actually have to race against half of the BCH public nodes.

We plan to test the success rate of this attack on BCH main net.

Attack scenario #2: reverse respend.

In this case we are going to leverage the delta in admission policies to create a reverse-respend attack.

Output A has 25 unconfirmed ancestors, output B has 0 unconfirmed ancestors.

Attacker will use A to "partition" the network. It will use a transaction (TX1) that spends A+B, and thus is 26th unconfirmed in BU mempool and a new one ,TX2, that spends B only, and thus is the 1st unconfirmed transaction in ABC mempool.

The final step consist in broadcasting TX1 to a miner running BU while broadcasting TX2 to merchant running ABC.

This will indeed create a reverse respend attack.

Attack scenario #2: solution

To completely solve the problem BU added a constraint on transactions that has more than 25 parents, which is that those could spend only one input5.

This way once TX1 got broadcasted it won't be accepted by the BU nodes (despite that BU nodes accept chain longer than 25) the same way all other nodes of the network are going to do. The rejection is caused by the fact that the transaction is trying to spend 2 outputs.

This won't let the attacker to partition the network, i.e. only TX2 will be include in nodes mempool independently from the fact that ABC or BU are run.

At the same time this new constraint would let us have longer chain of unconfirmed transactions anyway as long as the 1-UTXO-only constraint is respected, i.e. spent UTXO which has more than 25 unconfirmed parents.

The constraint we described is more strict that what we need, we could have let TX1 to spend more than one output as long as this outputs have more than 25 ancestors.

Footnotes

[1] Standard Priority (SP) Miner Policy and Double-spend Proof Relay

[2] Instant Transactions Workshop, October 2018, Gragnano, Italy

[3] According to Peter Rizun's presentation "Empirical Double spend Probabilities for Unconfirmed Transactions" if a merchant wait for more that 2 seconds after TX1 has been broadcasted before delivering the good, he has 99.9% chance of detecting a fast respend DS

[4] BitcoinUnlimited/BitcoinUnlimited#1109

[5] Thanks to checksum0 for coming with the idea,that has been implemented in BU with this PR BitcoinUnlimited/BitcoinUnlimited#1998

[6] BU Unconfirmed Transaction Chain Limits documentation

[7] Quasi-Consensus and the Unconfirmed Transaction Chain Limit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment