Full RBF, while contentious, is essentially a matter of time, either through incentivized miners or through individual nodes.
This is an opinion editorial by Shinobi, a self-taught educator in the Bitcoin space and tech-oriented Bitcoin podcast host.
Big surprise, Bitcoiners are arguing furiously about a proposed change set to be included in the next release of Bitcoin Core. Opt-in replace-by-fee (RBF) is a mempool policy feature that was proposed in 2015 to give users a tool to deal with quick spikes in fees that lead to their transactions being stuck unconfirmed in the mempool for long stretches of time.
Obviously, this will be a problem for any use of Bitcoin if transaction volume grows on average to be consistently higher than the number of transactions that can be processed in the blockchain, so unless you think that will never happen this is a needed functionality on the network.
Transaction replacement was actually included and possible in the original release of the software before Satoshi Nakamoto disappeared. He eventually disabled the feature because the way he originally implemented it created a vector for denial-of-service attacks against nodes. His implementation allowed the replacement of any transaction without paying a higher fee, which essentially would have allowed users to send a transaction and then start broadcasting an unrestricted amount of replacements to the network. This would obviously allow the spamming of nodes with massive amounts of data that required no proof-of-work and would prohibitively increase the cost of running a node.
Over the years a few different proposals for a revamped and safer transaction replacement scheme have been discussed. We’ll quickly go through all of these.
The simplest variant of RBF. Any transaction can be replaced as long as the replacement of the original transaction is paying a higher feerate than the one it is replacing. That way transactions are all replaceable, but the requirement to pay a higher fee each time you replace one prevents an infinite spam of new versions of the transaction overloading nodes.
This proposed allowing all transactions to be replaced in the mempool, with one special caveat; all of the outputs in the original transaction must also be included in the replacement transaction, including the change output. It still requires increasing the fee to replace a transaction, but the requirement to maintain the same outputs means you have to add a new input and a second change output, because none of the original outputs can be altered. This results in larger transactions that have to pay more in total fees to ensure the replacement is paying a higher fee rate.
Here was a proposal to allow any transaction to be replaced in the mempool, but only after a certain number of blocks had passed since the node saw the original transaction. The idea was that this would allow stuck transactions in high fee environments to be replaced and confirmed faster, but the time delay in how soon it could be replaced would prevent zero-confirmation double spend attempts.
This is what was implemented in 2016 as defined in BIP 125. Transactions can only be replaced if they set a specific flag in the transaction opting into replacement, or if one of their ancestors did in the case of a chain of unconfirmed transactions, to allow people receiving funds to know whether or not an unconfirmed transaction will be replaceable in the mempool.
The big controversy today is that the next release of Core, 0.24, is set to introduce a full RBF mempool policy flag. What does this mean? It will give users a configurable option to change their local mempool policy from opt-in RBF to full RBF; by default the option will be left off (the nodes will be using full RBF). So why are people up in arms over this change? Businesses that accept zero confirmation transactions depend on the super majority of nodes’ mempools refusing to replace transactions that haven’t opted into RBF with a transaction flag. They do this by tactically connecting their node to a large number of other nodes spread all across the network. This allows them to very quickly detect the presence of a double spend transaction on the network, as it has to be done almost immediately if a transaction is not flagged as RBF to have a good chance of making it to miners. It’s also worth pointing out that every business on the network can’t do this without effectively sybiling the network. These businesses claim that full RBF “breaks” their business model of using RBF. Some have even criticized Core developers as “forcing” a change that negatively affects these businesses.
The simple reality is that double spending has and always will be possible, opt-in RBF or full RBF does nothing to change this. Furthermore, simply creating an option to change your own local mempool policy (that is set to off by default) is in no way dictating change to anyone, it is an option given to users to make a choice for themselves. At the end of the day when it comes to which transactions are actually going to be included in the next block, the only mempools that matter are miners’. The mempools of individual users nodes are nothing but a daisy chain of memory storage with the ultimate goal of propagating all of those unconfirmed transactions to the miners so they can be included in a block eventually.
Mempool policy is used as a sort of soft safety mechanism to prevent denial-of-service attacks on nodes and protect users from shooting themselves in the foot with complicated transactions and scripts. Many types of transactions are valid by consensus, are allowed to be included in a block, but will not be relayed by nodes’ default mempool policy. This however does nothing at all to stop a determined user from relaying a transaction that would be ignored by nodes on the network directly to a miner.
That’s the crux of the matter. All it takes is miners setting up an API to directly submit transactions to them, which many already have, and the restrictions of mempool policies across the network don’t matter. You can just give a transaction directly to the miners and bypass every rule on when something can be replaced in the mempool of other nodes. Think about the incentives of that — if there is money to be made by mining a certain class of transactions, but mempools across the network won’t relay them, what would you do as a miner? Just accept them directly. The more the subsidy reduces and transaction fees grow as a percentage of miner revenue, the more inevitable it becomes that miners will just directly accept replacements that pay higher fees if nodes on the network will not relay them indirectly. It’s inescapable.
This change does not alter the default mempool policy for Bitcoin Core, it simply presents an option for an individual node operator to alter their local mempool policy if they so choose.
And I might add, this is a choice that has always been available if users chose to modify their client. All it does is make a choice that has always been available to users simpler to do. The incentives inevitably lead to the state where all transactions will be replaceable if miners act in an economically rational way — it’s unavoidable. The only question of the matter is, should the software reflect those incentives, in a way letting individual users decide for themselves what policy to use for their mempool, or should people just sit around and let the propagation of transactions centralize around direct submission to miners themselves?
The end result is the same, but waiting for miners to gravitate to direct transaction submission will have very negative consequences. It would have privacy implications for people broadcasting transactions to the network, and it could have very negative consequences for users’ ability to decide what fee to pay for a transaction. If large portions of pending transactions are no longer publicly broadcast across the network, then users will have an incomplete view of who they are bidding against for inclusion in a block. Miners could even lie about the fee distribution in order to incentivize users to pay more than they have to.
The only real downside to making this option available is that full RBF might not work consistently if only a small amount of the network, including miners, choose to enable full RBF. However, this fundamentally isn’t any different in terms of transitioning than the upgrade to SegWit was. During that transition period, non-upgraded nodes would not relay SegWit transactions because they were incapable of validating them, so during that period there was the same dynamic of propagation being inconsistent until enough users upgraded. But ultimately, that didn’t change the fact that upgrading was a decision for individual users to make.
Ultimately fighting full RBF is just denying the reality of the incentives on the network. Nothing is being dictated to anyone, a configuration option is simply presenting individual users with a choice to make for themselves. I find it odd that simultaneously, so many people are both ignoring the reality of incentives to argue an insecure means of receiving payments can be kept secure in defiance of incentives, just as people are arguing that software users should not be allowed a choice in how to configure their own software.
My node, my rules, right?
This is a guest post by Shinobi. Opinions expressed are entirely their own and do not necessarily reflect those of BTC Inc or Bitcoin Magazine.