Subject: [bitcoin-dev] Full-RBF testing: at least 31% of hash power, over at least 4 pools, is mining full-RBF right now

From: Peter Todd <[email-masked]>
Date: Wed, 16 Aug 2023 10:25:58 +0000

Since Andrew Chow criticized my use of OTS(1) to measure full-RBF adoption,
I've been doing high-fee full-RBF testing to re-confirm my findings.
Specifically, that means sending a high fee tx1 with a fee more than sufficient
to get mined in the next block. Then 30 seconds later, I send tx2, a double
spend with an even higher fee, removing one of tx1's outputs. Propagation was
verified for each full-RBF double-spend by checking debug.log on another very
well-connected node.

Results: >31% of hash power, over at least 4 different pools, is mining
full-RBF at the moment, assuming Binance Pool is mining full-RBF with half
their hashing power (see below for details). This finding confirms my OTS
calendar research, which found similar results.

Specifically, in my testing yesterday I successfully did the following full-RBF
double-spends:

Antpool: 2ebe68edca320dabdd8b39ebae5f18efaac829055058a2c0f4bc2b37c69cd88c
         dac9895795efa3956cc775b4f48a5d2b01fa0ea0d7a915fa350baa4779d2e0e9
         b7d43485bf8f0f9792ba6889ab2f53fb462aa4997f3995d9d027375993fa7907
         e2cd91093399dcad5ad3fd73627e497c5e808434ecc7aaec13d9d488973f099c
         5bb7e7d6c34dfd2ae65466a2968a0e500ef25d9b70f7f2b299203dffc1a1b10d
         ad7d2f74eab240726604dfd66231f52ac7778567028cf818387dc9395474f63b
         1ddb11bad477e8b5bcdb36dbaa26065ae8e3c37b39b37a2b34780b98274bd076
         f16bb35670b66ab3c8ccbbaf5f06da5f311e9b05a02b23a77a6fec5e8e5951a4
         b6123a7c126b7937a23bf93cce09358bc2c1047a3bd20fad47bf187e453aadc5
         66f3da902d43ab0a2561d0477c7050d057bb0f69ade79015494363ad08ed172d
         17a6995a757e027b2a51b9cc58635b29553ccc6c164555c0ed922074a23bcbfe
Poolin: 68ca9ee95748dc98ba24018ea64c18de31fca552e4753ef012acd0b615cd7384
        477089a1e997a0115b3d4cd1d4ce21eb9dc83c45c14a7f7441e4fc74c3649ba2
EMCDPool: dde0975ad42fd9e03677f64b6c4f7efbe2ec0b6f905206d47893a77ac6336fca
          a0131d4f8cc13d70443cd87f2ee7543e1142640666a88f80d1e0c885c7eb2c12
Binance Pool: fb62691537d92f61dcb8ace979e0947b47dcbc7e9f50e79f77059ba0a669cdb5
              637c58f3c0447ee99808b37e4f9559096c00ceb0d21130a9254558c4d2d7ae63

Anyone running a full-RBF node with debug=mempool can easily verify all these
double-spends by examining their debug.log files.

With Antpool, Poolin, and EMCDPool, it is most likely that they're mining
full-RBF with ~100% of their hash power. These pools mined every double-spend
available to them, with the exception of some Antpool blocks found very close
to when the double-spend was broadcast. Binance Pool did *not* mine a full-RBF
replacement on two occasions, which makes me suspect they're mining full-RBF
with less than 100% of their hash power. During this testing, Binance Pool,
AntPool, Poolin, and EMCDPool, also all mined multiple double-spends from my
OTS calendars, further confirming my findings.

My OTS research also found examples of KuCoinPool and ULTIMUSPOOL mining
full-RBF double spends. They didn't find any blocks during this testing, so I
have no data on them with this testing. Luxor _did_ mine some blocks without
mining the double-spends, so at the moment it's reasonable to assume they have
full-RBF fully or partially disabled, or have some kind of full-RBF propagation
issue.  They have confirmed similar issues to me in the past (eg employees
unintentionally disabling it on some nodes during an upgrade), so it's likely
that has happened again. MARA Pool also mined some blocks without mining
double-spends, so they too may have full-RBF fully or partially disabled, as I
mentioned in my OTS research.(1)

The tool I used is the following:

    https://github.com/petertodd/replace-by-fee-tools/blob/master/doublespend.py

Note that this script was written years ago, pre-segwit, and I hastily updated
it for recent Bitcoin Core/python-bitcoinlib versions. I haven't checked if all
the options like OP_Return outputs and multisig still work, and it doesn't even
take segwit into account when calculating fees. Don't use it on a wallet with
funds you can't afford to lose; it definitely has bugs in it.

For reference, here is the logs from a successful double-spend attempt:

	$ sleep 15 ; ./doublespend.py --fee1 0.00018 --fee2 0.000224 `/home/user/bitcoin/src/bitcoin-cli getnewaddress` 0.00001
	DEBUG:root:Delta fee: 0.00002296
	DEBUG:root:Adding new input caec040f4435e98de9ae44a385e301312c5a3cddfb33f1bd08e1cf63307f87ce:0 with value 0.00072549 BTC
	DEBUG:root:Delta fee: 0.00003035
	DEBUG:root:Payment tx 01000000000101ce877f3063cfe108bdf133fbdd3c5a2c3101e385a344aee98de935440f04ecca0000000000ffffffff028a0f0100000000001600149e12f3ef33ba4ccde4b85978e675c9fe59bb24a2e8030000000000001600149049e0f57ec5899c1eed2c5e9aab1c34ff5cec1f02473044022063834a187727c1eceb9b3e6ae9ccd0d369b51af3493fafba1d61ed3b273d48f7022049fbe71ecd600c7345fb6002e04275eb8445031df746eceaa6e6f5f413f67497012102c56d86e3031851822485d1a2f9f0e402f14b96b64e711d5a2567412d1ea49a8b00000000
	INFO:root:Payment tx size: 0.222 KB, fees: 0.00002035, 0.00009166 BTC/KB
	INFO:root:Sent payment tx: 1c28870a78efd1c4616726ea0ca3f9d67f5591aab415222e2c9ec6184fc0b4f2
	INFO:root:Sleeping for 30 seconds
	DEBUG:root:Delta fee: 0.00004279
	DEBUG:root:Double-spend tx 01000000000101ce877f3063cfe108bdf133fbdd3c5a2c3101e385a344aee98de935440f04ecca0000000000ffffffff01ae0a0100000000001600149e12f3ef33ba4ccde4b85978e675c9fe59bb24a20247304402201289c26da70e9ec4424fc2ff7194b57384c78c9c986c2efe6771ac6f5fda199702200cefa72560f21cd9abe846078ce13197029562102f7a44b8ec50772a851c1799012102c56d86e3031851822485d1a2f9f0e402f14b96b64e711d5a2567412d1ea49a8b00000000
	INFO:root:Double-spend tx size: 0.191 KB, fees: 0.00004279, 0.00022403 BTC/KB
	INFO:root:Sent double-spend tx: fb62691537d92f61dcb8ace979e0947b47dcbc7e9f50e79f77059ba0a669cdb5

Remember that if you want to replicate this, don't be surprised if it takes
quite a few attempts if you're sending tx1 with next-block fees. A minority of
hash power is mining full-RBF. There's also a chance that in the ~30s or
whatever you wait between tx1 and tx2, a block is found and tx1 gets mined.
This chance is actually even higher than the ~5% you'd expect, because miners
don't instantly update their block templates.

So if ~30% of hash power is actively mining full-RBF, you might actually have a
~20% chance per attempt at succeeding at a naive high-fee/higher-fee
double-spend. Thus there's a (1-20%)^10 = 11% chance that 10 attempts in a row
fail. Being that unlucky happens all the time; the Gods of Probability,
probably hate you. :)

Finally, research like this is expensive in terms of my time and transaction
fees; research via the OTS calendar approach is essentially free. Donations are
appreciated as no-one is paying me to do full-RBF work or covering these
expenses.

Cheapest/easiest way is via Lightning: https://stacker.news/petertodd

Or on-chain: 1FCYd7j4CThTMzts78rh6iQJLBRGPW9fWv

# References

1) https://github.com/bitcoin/bitcoin/pull/28132

-- 
https://petertodd.org 'peter'[:-1]@petertodd.org