Double-Spend Proofs work WITH Unified Mining Policies. They Are Not a Substitute for Them.

Jonald Fyookball
6 min readNov 14, 2019

--

Bitcoin Cash needs to have fast, cheap, reliable transactions. This reliability depends on zero-confirmation (“0-conf”) transactions working consistently. And so far, it does. This is because miners and mining pools are consistently applying the same policies for transactions.

Recently, the leaders of Bitcoin Unlimited have informally proposed the idea of having non-unified mining policies, combined with double-spend proofs and other techniques, as a way to allow some mining nodes to mine longer transaction chains than others. However, analysis shows that double-spend proofs, while useful in certain cases, do almost nothing to fix the problems arising from non-unified mining policies. Therefore, this is not a good plan.

Consensus Vs. Policy

To review: for any transaction to be valid on the Bitcoin Cash network, it has to follow the network’s consensus rules. If it doesn’t follow the rules, no miner can include it in a block because other miners will see the block as invalid and won’t build on it.

There is also another layer of rules on top of the consensus rules which make some further restrictions, and this is called policy. Because it’s literally “not consensus”, that means that every node could theoretically set their own policy and the chain wouldn’t split.

But just because the chain doesn’t split doesn’t mean there won’t be issues. For example, if you’ve ever sent a transaction with too low of a fee and the network rejected it, it’s because the node you connected to considered it “non standard”. In other words, it wasn’t accepted by policy.

Similarly, the “25 chained transactions limit” is also based on a policy, and just as with fees, your transactions may be rejected by the network (more on this in a moment).

Double-Spends

For the purposes of this article, let us consider two main kinds of double -spends:

1. “race condition” double spends
2. “divided policy” double spends.

(There’s also various miner-created double spends and malleation-based double spends, which won’t be delved into.)

Race Condition Double-Spends

The first kind of double-spend (“race condition”) occurs when Alice attempts to broadcast two different transactions from the same UTXO at the same time, perhaps one to a merchant and the other back to herself. If the second transaction gets into a block, she succeeds in her double-spend.

Miners historically have had unified policies and only accept a transaction if it’s the “first seen” instance based on the input UTXOs. Thus, within a few seconds of a transaction being sent on the BCH network, all nodes know about it and will reject a double spend based on this “first seen” rule.

This unified policy is what makes the network reliable for 0-conf. That is why Alice has to broadcast at nearly the exact same time if she wants to have any chance.

Divided Policy Double-Spends

The second kind of double spend would come from inconsistent mining policies across the ecosystem. This makes double spending much easier and doesn’t require a fast response, or even necessarily custom software.

For example, if miner Alice has a minimum block and relay fee policy of 1 sat/byte, and miner Bob is at 2 sat/byte, then Charlie can double spend a merchant by making sure to broadcast his transaction to Alice with a 1 sat/byte fee. He knows Bob didn’t accept this first transaction, so he then double-spends using miner Bob with the same coin and a 2 sat/byte fee, sending the money back to himself.

The same thing happens with the 25-tx limit. If miner Alice only accepts chains of 25 transactions or less, and miner Bob accepts 50, then Charlie would do a similar maneuver: He would spend first with the miner using the more relaxed policy (Bob) using a mixed set of short-chain UTXOs (or already confirmed UTXOs), and some long chain UTXOs that are too long for Alice. He then double-spends only the short-chain UTXOs with miner Alice.

Unspendable Coins

There’s an even bigger problem in the specific case of long transaction chains and non-unified policy. This isn’t just about double spending. Normal users (who aren’t trying to double spend) will find that some of their transactions will be rejected if the chain is too long.

The 25-transaction limit is a policy setting. If miners have differing policies, then certain transactions will be valid on part of the network and invalid elsewhere. So by having only some miners accept longer chains, we don’t actually solve the problem. We would only achieve enabling and encouraging some users to make long chains that will produce semi-unspendable coins by others until they get confirmed.

This is a worse problem than for the case of inconsistent fees because it means that even if the user behaves correctly, they sometimes still won’t be able to spend a coin. In fact, there is nothing the user can do to spend the coin, unless they wait for an unknown number of confirmations or they intentionally broadcast their transaction directly to a miner that does accept the coin.

What’s a Double-Spend Proof?

The idea behind a double spend proof is to look in the mempool(s) for a double spent coin, and then send an alert to a node, business, or user. Implementing double spend proofs require substantial changes to the whole stack, from the nodes, to RPC servers, to wallets.

These alerts may help with the “race condition” type of double spends. If a merchant is using a double spend proof system, he can get an alert to see if there was an attempt to re-spend the coin and try to catch naughty Alice before she leaves the store.

Thus, in the case of retail shoplifting, the alert can patch the small security hole that may be exploited by a double-spender, so it is helpful.

Why Double Spend Proofs Don’t Fix Inconsistent Mining Policies

The main reason that double spend proofs don’t fix inconsistent mining policies is that these proofs can only be used as an alert, (a notification or message). They don’t actually prevent double spending or compel nodes to change their behavior.

Nodes control their own policies. Even if node Alice were to send a message to node Bob telling him about an alternate transaction, the alternate will be dropped either because it’s invalid or wasn’t first-seen.

Using “alerts” to disincentive bad behavior is theoretically possible, but it’s a fragile approach. It means we are allowing double spends and reacting after the fact. Any additional behaviors needed for security reasons would need to be coded for each application. This is difficult or unworkable for many or most use cases. It reminds me of the Lightning Network in that it takes an existing system that functions well, breaks it… and then tries to add another system on top to fix what just got broken.

It is much better and more reliable to simply prevent most double spends in the first place, as we currently do.

The second reason that this isn’t a solution is because of the unspendable coins problem mentioned earlier. This isn’t helped at all because it’s not a double spend.

On a side note: the one use-case best suited to double spend proofs (a retail setting) would now also become broken if we had inconsistent policies, since a shoplifter would have a much bigger time window to attempt their double spend. (They would do it several minutes after they leave the store.)

The “BU Overlay Network”

Part of the BU plan is to introduce an “overlay network” which will forward transactions to peers as soon as those peers’ policy would accept them (in future blocks). But this too, fixes neither the problem of easy double spends, nor the unspendable coins problem. All it does is re-broadcast transactions to the network that weren’t accepted in the hopes they will meet policy on subsequent blocks.

Getting delayed by one block is the best case scenario. And if one node has a policy allowing 20 times longer transaction chains, then this process could repeat for 20 blocks. In other words, your transaction could be hanging around in the mempool for as many as 20 blocks before being confirmed, and even then, you’d still have to explicitly send your transaction to a BU node to begin with.

The worst part about this overlay idea is that it encourages “first class citizens” and “second class citizens” in terms of nodes. The nodes with the more relaxed policies would be pushed and promoted as being the “first receivers” which would then dole out transactions to other nodes as their policies allow.

This would set a very bad precedent and have a centralizing effect. Bitcoin works best when any miner can include your transaction in a block.

Conclusion

We should continue the current system of unified miner policy that supports 0-conf transactions. This is a key ingredient for Bitcoin Cash’s fast, cheap, and reliable payments, and helps the network run like clockwork.

Bitcoin Unlimited’s plan to combine inconsistent policies with double spend alerts and re-broadcasting of transactions is both fundamentally unsound and overly complicated. It will cause problems and is clearly the wrong decision for Bitcoin Cash.

--

--