Since it takes about 10 minutes to confirm the average bitcoin block, many crypto machines, exchangers and bitcoin merchants face the problem of fast payment processing. A dilemma arises: can a payment already be considered received if the deposit transaction is in the mempool but not yet confirmed? Simply put, how feasible is it to replace or cancel a transaction that has already been added to the mempool?
What is RBF
RBF (Replace by feat) – replacing an unconfirmed transaction with a new transaction with a higher network of the network. By replacement, it is meant that the new transaction uses the same input as the original.
The physical meaning of RBF is that it is more profitable for the miner (block creator) to take the transaction with the higher commission. And since the transactions have the same incut, the second transaction becomes invalid.
In 2016, the Bitcoin Core node update v0.12.0 was released.
Which included support for OPT-in RBF. This is a function that allows you to create transactions with a special flag that signals that the transaction can be replaced. Technically, this looks like this: each transaction has its own serial number nsequence,
determining the sequence of transactions to the block. And in order to make the transaction potentially indispensable, it was necessary to indicate the maximum possible serial number – 0xfffffffffffffffff
. For example, Blockchein explorer Mempool.space indicates this clearly:
According to Bitcoin protocol rules, all repeated transactions with the same intuition must be rejected and not propagated further through the network by the nodes. This rule is called the first seen rule. At most, it used to be.
The Bitcoin Core 24.0.1 node update was released in December 2022.
Which includes full-RBF. This is a function that allows nodes to process repeated transactions and consider them legitimate. By default, this function is disabled in a node, so in the node settings you must set the parameter mempoolfullrbf=1
As of February 2023, almost 30% of all Bitcoin nodes have switched to version 24.0.1:
According to the study, at least 17% of all 24.0.1 nodes activated full-RBF.
Step-by-step instructions for replacing transactions
I decided to deploy the Bitcoin v24.0.1 node and try to replace the transaction. Below is a step-by-step action plan.
Bitcoin Core system requirements 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. Mac OS X.
I actually took about 480 GB, so it’s better to have more disk space.
1. Download the Node Bitcoin Core v24.0.1
Download the patched Bitcoin Core node v24.0.1. The node specifically connects to peers that support full-RBF and promote repeat transactions across the network:
git clone -b full-rbf-v24.0.1 https://github.com/petertodd/bitcoin.git
Or you can download the original node and then in the settings specify the peers that have full-RBF. This will be described below.
2. Compile the sources and run the node
First, we set up 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
Mac OS:
brew install automake boost ccache git libevent libnatpmp libtool llvm miniupnpc pkg-config python qrencode qt@5 sqlite zeromq
Next, compile the Bitcoin node:
./autogen.sh
./configure
make
If you want to run compilation on several cores at once, then you need to set the appropriate parameters for the make
command:
Linux
make -j "$(($(nproc) + 1))"
Mac OS
make -j "$(($(sysctl -n hw.physicalcpu) + 1))"
On my 8 GB RAM and 4 cores it took about 15 minutes to compile.
3. Create a configuration file bitcoin.conf
The file must be created in the ./bitcoin
root folder.
There is even an online config generator:
I needed the following parameters during the experiment:
mempoolfullrbf=1 #Включает full-RBF функционал
txindex=1 #Индексирует внешние транзакции, которые не принадлежат кошельку ноды
datadir=<dir_path> #Если необходимо сменить директорию, куда нода будет загружать все данные
I will dwell on the txindex=1
parameter in more detail. 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 the original node and you want to add peers with full-RBF enabled, 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
4. Run a node and create a wallet
Run the node using the ./bitcoind -daemon
command. If you do not want to run the node in the background, then run without the -daemon
parameter
Then the node should begin to synchronize, in my entire process took 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 the teams are available here:
After full synchronization, it is necessary to create a wallet. This can be done in different ways (import, generate), for example, create a command createwallet:
./bitcoin-cli createwallet "testwallet"
5. Prepare the script
To begin with, you should make sure that you can turn to the local Bitcoin node through python-bitcoinlibСode>:
python3 /lib/python-bitcoinlib/examples/ssl-rpc-connection.py
Then you can take as the basis of dublespend.py Сode>and make the following:
- Send the first transaction with a network fee much lower than the current transactions in the mempool. Thus, the transaction will be “stuck” in the mempool and will not get into the block;
- Wait a minute for the transaction to spread across the network;
- Send a second transaction with a network fee many times higher than the current transaction in the mempool. Thus, the miner will be motivated to take exactly the second transaction in the block.
Summary
I conducted the experiment several times – the result was the same. Let’s look at an example of one of the iterations:
Creation time | Network fee | |
transaction №1 | 00:00 | 0.0000113 BTC (0.26$) |
Transaction №2 | 00:19 | 0.004068 BTC (±94$) |
I sent the first transaction from Network Fee = 0.26 $. This is significantly lower than market conditions. Despite the fact that the second transaction had Fee at $ 94, miners (the creators of the blocks) still did not take it. That is, replace-by-Fee did not work .
It is noteworthy how blockchain explorers reacted to repeated transactions. Basically all displayed only the first transaction (e.g., mempool.space or blockchair). Blockcypher explorer displays repeated transactions and warns about double-spend:
I assume that miners cannot take a re-transaction to a block because that block will be rejected by the majority of network participants. And as long as Bitcoin Core v24.0.1 with full-RBF turned on has a minority of participants, transaction swapping will not work.
Read more articles about cryptocurrencies and mining at COOL-MINING.ORG.
Do you like to read similar articles about cryptocurrencies and mining, do you want to support me as an author or ask questions? Be the first to know the news, subscribe to my telegram channel