Checking if full-RBF works in Bitcoin

ATMs, crypto exchanges, merchants, and everyone else who accepts bitcoin have the task of processing payments as quickly as possible. Given the average bitcoin block confirmation of 10 minutes, the question arises: is it possible to count the receipt of a payment if the deposit transaction is in the mempool and has not yet been confirmed? In other words, how realistic is it to replace or cancel a transaction that is already in the mempool?

TL;DR: I deployed my Bitcoin Core v24.0 node, which supports full-RBF and tried to replace the transaction – it didn’t work for me.

More news about product management, technology and entrepreneurship in crypto in my telegram channel: @grin_channel

What is RBF and why it became relevant

RBF (replace by fee) – replacement of an unconfirmed transaction with a new transaction with a higher network fee. By replacement, we mean that the new transaction uses the same input as the original one.

The physical meaning of RBF is that it is more profitable for the miner (block creator) to take a transaction with a higher commission. And since the transactions have the same input, the second transaction becomes invalid.

Back in 2016, a node update was released Bitcoin Core v0.12.0, which included Opt-in RBF support. This is a feature that allows you to create transactions with a special flag signaling that the transaction can be replaced. Technically, it looks like this: each transaction has its own serial number nSequence, which determines the order in which transactions are taken into the block. And, in order to make a transaction potentially indispensable, it was necessary to specify the maximum possible sequence number – 0xffffffff. For example, the mempool.space blockchain explorer explicitly states this:

Source: https://mempool.space/
Source: https://mempool.space/

According to the rules of the Bitcoin protocol, all repeated transactions with the same input must be rejected and not propagated by nodes further through the network. This rule is called the first seen rule. At the very least, that’s how it used to be.

Node update released in December 2022 Bitcoin Core 24.0.1, which includes full-RBF. This is a feature that allows nodes to process repeated transactions and consider them legitimate. By default in the node, this function is disabled, so in the node settings to activate it, you must set the parameter mempoolfullrbf=1

As of February 2023, almost 30% of all Bitcoin nodes have migrated to version 24.0.1:

Source: https://bitnodes.io/dashboard/1y/
Source: https://bitnodes.io/dashboard/1y/

According to researchof all nodes in version 24.0.1, at least 17% have activated full-RBF.

Step-by-step instructions for replacing transactions

I decided to deploy a Bitcoin v24.0.1 node and try to replace the transaction. Below is a step by step action plan.

System requirements Bitcoin Core from bitcoin.org:

  • disk space. 350 GB.

  • download. 500 MB/day (15 GB/month)

  • upload. 5 GB/day (150 GB/month)

  • Memory (RAM) 1 GB.

  • System. desktop. laptop. Some ARM chipsets >1 GHz.

  • operating system. Windows 7/8.x/10. MacOS X.

It actually took me about 480 GB, so it’s better to put in more disk space.

Step 1. Download the Bitcoin Core v24.0.1 node

Download the patched node Bitcoin Core v24.0.1. The node specifically connects to peers that support full-RBF and help propagate retransactions across the network:

git clone -b full-rbf-v24.0.1 https://github.com/petertodd/bitcoin.git

You can read more about this node Here. Or you can download the original node and then in the settings specify the peers that have full-RBF. This will be further described below.

Step 2. Compile the sources and run the node

First, install all the necessary dependencies.

linux:

sudo apt-get install automake autotools-dev bsdmainutils build-essential ccache clang gcc git libboost-dev libboost-filesystem-dev libboost-system-dev libboost-test-dev libevent-dev libminiupnpc-dev libnatpmp-dev libqt5gui5 libqt5core5a libqt5dbus5 libsqlite3-dev libtool libzmq3-dev pkg-config python3 qttools5-dev qttools5-dev-tools qtwayland5 systemtap-sdt-dev

MacOS:

brew install automake boost ccache git libevent libnatpmp libtool llvm miniupnpc pkg-config python qrencode qt@5 sqlite zeromq

Next, we compile the Bitcoin node:

./autogen.sh
./configure
make

If you want to run compilation on several cores at once, then for the command make you need to set the appropriate parameters:

linux

make -j "$(($(nproc) + 1))"

MacOS

make -j "$(($(sysctl -n hw.physicalcpu) + 1))"

It took me about 15 minutes to compile on 8 GB RAM and 4 cores. If you have problems at this stage, you can see the Troubleshooting section Here.

Step 3. Create a configuration file bitcoin.conf

The file must be created in the root folder ./bitcoin. There are even online config generatorI needed the following parameters during the experiment:

mempoolfullrbf=1 #Включает full-RBF функционал
txindex=1 #Индексирует внешние транзакции, которые не принадлежат кошельку ноды
datadir=<dir_path> #Если необходимо сменить директорию, куда нода будет загружать все данные

I will dwell on the parameter txindex=1. If you do not enable this setting, then the node will not be able to access the input and output parameters of transactions that are not related to the node’s wallet. This can be useful when you are trying to resubmit a transaction using the same input, which is in fact a link to the output of the outer transaction. This option will require an additional 20 GB of disk space to store indexed data.

If you have an original node and want to add peers with full-RBF enabled, then add the following parameters to the configuration file:

addnode=full-rbf1.btc.petertodd.net
addnode=full-rbf2.btc.petertodd.net
addnode=full-rbf3.btc.petertodd.net
addnode=full-rbf4.btc.petertodd.net

The list of peers with full-RBF enabled is taken Here.

Step 4. Run the node and create a wallet

Run the node using the command ./bitcoind -daemon. If you do not want to run the node in the background, then run without a parameter -daemon

Then the node should start synchronization, the whole process took me about three days.

You can access the node using bitcoin-cli. For example, you can see how many blocks have already been downloaded with the following command: ./bitcoin-cli getblockcount. All commands are available Here.

After full synchronization, you need to create a wallet. This can be done in different ways (import, generate), for example, create with the command createwallet:

./bitcoin-cli createwallet "testwallet"

Step 5. Prepare the script

I used python scripts from here.

The first thing to do is to make sure that you can access the local Bitcoin node via python-bitcoinlib:

python3 /lib/python-bitcoinlib/examples/ssl-rpc-connection.py

Next, you can take as a basis doublespend.pyand do the following:

  1. Send the first transaction with a network fee that is significantly lower than the current transactions in the mempool. So, the transaction will “get stuck” in the mempool and will not get into the block;

  2. Wait a minute while the transaction propagates over the network;

  3. Send a second transaction with a network fee that is several times higher than the current transactions in the mempool. So, the miner will be motivated to take exactly the repeated transaction into the block.

What happened in the end

I ran the experiment several times – the result was the same. Consider one of the iterations as an example:

Time of creation

network fee

Transaction #1

00:00

0.0000113 BTC ($0.26)

Transaction #2

00:19

0.004068 BTC (±94$)

I sent the first transaction with network fee = $0.26. This is well below market conditions. Despite the fact that the second transaction had a fee of $94, the miners (block creators) still did not take it. That is replace-by-fee didn’t work.

It is noteworthy how blockchain explorers reacted to repeated transactions. Basically everyone only displayed the first transaction (like mempool.space or blockchair). The Blockcypher explorer displays repeated transactions and warns about double-spend:

Source: https://live.blockcypher.com/
Source: https://live.blockcypher.com/

My guess is that miners can’t take a retransaction into a block as that block will be rejected by the majority of the network. And as long as a minority of participants have Bitcoin Core v24.0.1 with full-RBF enabled, transaction replacement will not work.

If you liked the article, then subscribe to my telegram channel, where I talk about product management, technology and entrepreneurship in crypto: @grin_channel

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *