📜 ⬆️ ⬇️

Understanding Bitcoin Replace-By-Fee Transactions

Hello! In this article, we will understand what a Replace-By-Fee transaction is and how to use it. Bonus! A couple of instructive stories at the end.

So, imagine a situation when A sends coins to B. He creates and signs a transaction, and releases it to the network for confirmation. Unfortunately, the transaction is not confirmed for a long time, the transaction is too low commission (or the commission is normal in normal circumstances, but at the moment the queue of unconfirmed transactions is too large and the miners prefer to mine transactions with higher commissions). What should user A do? Options: a) wait for confirmation (you can wait for a long time) b) wait for the transaction to be canceled (when most of the nodes decide to finally throw a transaction out of mempool) and you will be able to dispose of the released coins (that is, create transactions and pools will not accept them as double-spons) ) Replace the transaction with a commission increase (RBF)

So, RBF is the replacement of an existing transaction with a new transaction with an increase in commission. Replacing means that in the new transaction the same inputs will be used as in the old transaction, and this will not be considered a double-spread (read as fraud). As a result, only one transaction will be added to the blockchain (with high probability this will be a transaction with an increased commission).

RBF is described in bip-0125
')
Which transaction can be replaced? This is a good question. Replacement of transactions was provided by the creator of the system Satoshi Nakamoto, but turned off at some point. Then it was modified to RBF and included in the Bitcoin Core 0.12 and later code. To replace the transaction data, a special int field nSequence is provided, which signals which transaction is older than which one. For a transaction to be potentially replaceable, the nSequence value must be less (0xffffffff - 1).

By default, most modern wallets nSequence immediately put the maximum, and the ability to replace transactions must be enabled in the settings. This is how it looks in the Electrum wallet:

image

An example of a decoded transaction:

... "inputs": [ { "addresses": [ "...." ], "output_index": 0, "output_value": 1010000, "prev_hash": "...", "script": "...", "script_type": "pay-to-pubkey-hash", "sequence": 0 }, ... 

Sequence is specified for each transaction entry.

In the same Electrum wallet, after enabling the RBF option, it will be possible to increase the transaction fee directly in the GUI, but now we will be collecting the RBF transaction with our hands. What for? First, to figure it out, and second, for more flexibility, for example, in this case in the RBF transaction we will be able to specify completely different target addresses for translation than the attackers periodically try to use.

It looks like this: A wants to pay B. A creates, signs, and translates a transaction to transfer coins B, but deliberately puts a lower or zero commission. If B is not careful, he counts the unconfirmed transaction (and gives the goods to A, for example). After that, A replaces the transaction and redirects the output of the transaction to C, where C is controlled by A.

How can B avoid this? If, nevertheless, B prefers to count unconfirmed transactions (for speed), you should not count plastic transactions (where nSequence allows the transaction to be replaced). And in general, be suspicious of such transactions. If you once credited plastic transactions, it would be nice to double-check them for the fact of fraud and apply sanctions to the payer, if he cheats. And of course, it would be ideal to wait for at least 2x confirmations.

Example.

We will use the wonderful open source tool github.com/OutCast3k/coinbin with which you can manually create transactions with the inputs and outputs we need. Works completely in the browser without communicating with the server. The live version is available at coinb.in

Create a transaction through New → Transaction. We take a private key in WIF format and load available (unspent) exits for this key. In the Outputs tab, specify the target address, specify the amount. In Advanced Options, we don’t forget to check the box “Make this a RBF transaction” - in this case the transaction nSequence will be less than the maximum value. Click Submit.

image

Transaction created. Pay attention to the Transaction Fee - this is the difference between the available amount of coins in total from all inputs MINUS the sum of all outputs (in our case 1 output). The difference will be the commission that the miner will take for himself. In this example, it is specifically zero.

We press Sign, copy the received hex transaction there, the same private key, and sign the transaction:

image

We translate the transaction into the network (you can use any endpoint):

image

So the transaction looks like:

image

Now let's use RBF. We create a new transaction, the inputs are taken from the same WIF. But we will indicate completely different ways out! We indicate one of the outputs 1CWHWkTWaq1K5hevimJia3cyinQsrgXUvg - donate the address of the creator of coinb.in

Amount indicate such that the transaction fee was sufficient for quick confirmation.

image

Pay attention to the Inputs tab - if the source address is reusable and there are a lot of transactions on it, then we will have to manually register in inputs only those inputs that are included in the transaction we want to replace (remove the extra ones, leave only the necessary ones). There may be hundreds of inputs, and in some cases it can be a rather painstaking job.

Signing:

image

We are broadcasting:

image

This is how it looks now on blockchain.info. The new transaction has every chance to be included in the block before its previous version.

image

We wait. There is a confirmation:

image

We have just replaced the transaction with the help of RBF, and the coins were not sent to the address that they originally wanted.

Again about safety

Not always nSequence = MAX guarantees that the transaction is final and cannot be replaced. In fact, the “Make this a RBF transaction” checkbox could not be set, but:


So we come to the idea that any transactions without confirmation in at least 2 blocks are unreliable. Why in 2x and not 1m? The short answer is orphaned blocks.

Links and materials :


Bonus!

Story 1.

Somehow, one of the projects using my bitcoin payment gateway was hacked, and they put 2 BTC on a withdrawal. In that version of the gateway, a commission of 0.0001 BTC was hardcoded, which was quite small at that time. Time was enough to sort things out and replace the transaction with a refund, raising the commission to 0.1 BTC. The attackers are probably upset. Moral - use RBF for good!

History 2.

I bitcoin up on bitmedia.io . The account there is replenished by counting incoming transactions to the user's special top-up address, and adding the transaction amount to the total balance of the user. Only transactions with 6 confirmations are counted.

I wanted to replenish the balance as soon as possible, so when the first transaction hung, I replaced the transaction several times with RBF. When the transaction was confirmed - the balance was added to me as many times as many RBF replacements I did. I immediately wrote in support to fix the bug. In gratitude, the extra 0.3 BTC was presented to me as a bug bounty. Moral - check your systems for how they behave with RBF!

Source: https://habr.com/ru/post/327218/


All Articles