Проверяем работает ли full-RBF в Bitcoin

У криптоматов, криптообменников, мерчантов и всех других, кто принимают биткоин, стоит задача обрабатывать платежи как можно быстрее. С учетом среднего подтверждения биткоин блока в 10 минут, возникает вопрос: можно ли засчитать получение платежа, если транзакция на депозит находится в мемпуле и еще не подтверждена? Иными словами, насколько реалистично заменить или отменить транзакцию, которая уже находится в мемпуле?

TL; DR: я развернул свою ноду Bitcoin Core v24.0, которая поддерживает full-RBF и попытался заменить транзакцию — у меня ничего не вышло.

Больше новостей про продакт-менеджмент, технологии и предпринимательство в крипте в моем телеграм канале:  @grin_channel

Что такое RBF и почему это стало актуальным

RBF (replace by fee) — замена неподтвержденной транзакции новой транзакцией с более высокой комиссией сети. Под заменой имеется в виду, что новая транзакция использует тот же инпут, что и исходная.

Физический смысл RBF в том, что майнеру (создателю блока) выгодней взять транзакцию с более высокой комиссией. А так как у транзакций одинаковый инпут, то вторая транзакция становится невалидной.

Еще в 2016 год вышло обновление ноды Bitcoin Core v0.12.0, которое включило в себя поддержку Opt-in RBF. Это функция, которая позволяет создавать транзакции со специальным флагом, сигнализирующим о том, что транзакция может быть заменена. Технически это выглядит так: у каждой транзакции есть свой порядковый номер nSequence, определяющий очередность взятия транзакций в блок. И, чтобы сделать транзакцию потенциально незаменимой, нужно было указать максимально возможный порядковый номер — 0xffffffff. Например, блокчеин эксплорер mempool.space об этом указывает явно:

Источник: https://mempool.space/Источник: https://mempool.space/

По правилам протокола Bitcoin, все повторные транзакции с тем же инпутом должны быть отклонены и не распространяться нодами дальше по сети. Это правило называется first seen rule. В крайнем случае, так было раньше.

В декабре 2022 году вышло обновление ноды Bitcoin Core 24.0.1, которое включает в себя full-RBF. Это функция, которая позволяет нодам обрабатывать повторные транзакции и считать их легитимными. По дефолту в ноде эта функция выключена, поэтому в настройках ноды для ее активации необходимо задать параметр mempoolfullrbf=1

На февраль 2023 года почти 30% всех нод Bitcoin перешли на версию 24.0.1:

Источник: https://bitnodes.io/dashboard/1y/Источник: https://bitnodes.io/dashboard/1y/

Согласно исследованию, из всех нод версии 24.0.1 минимум 17% активировали full-RBF.

Пошаговая инструкция по замене транзакций

Я решил развернуть ноду Bitcoin v24.0.1 и попробовать заменить транзакцию. Ниже поэтапный план действий.

Системные требования Bitcoin Core с 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.

У меня по факту заняло около 480 GB, поэтому лучше заложить дискового пространства побольше.

Шаг 1. Скачиваем ноду Bitcoin Core v24.0.1

Скачиваем пропатченную ноду Bitcoin Core v24.0.1. Нода специально подключается к пирам, которые поддерживают full-RBF и способствуют распространению повторных транзакций по сети:

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

Детальней об этой ноде можно прочитать здесь. Либо можно скачать оригинальную ноду и затем в настройках указать пиры, у которых стоит full-RBF. Об этом будет еще описано ниже.

Шаг 2. Компилируем исходники и запускаем ноду

Вначале устанавливаем все необходимые зависимости.

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

Дальше компилируем ноду Bitcoin:

./autogen.sh
./configure
make

Если вы хотите запустить компиляцию сразу на нескольких ядрах, то для команды make необходимо задать соответствующие параметры:

Linux

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

Mac OS

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

У меня на 8 GB RAM и 4 ядрах компиляция заняла около 15 минут. Если у вас на этом этапе возникли проблемы, то можете посмотреть раздел Troubleshooting здесь.

Шаг 3. Создаем конфигурационный файл bitcoin.conf

Файл необходимо создать в корневой папке ./bitcoin. Есть даже онлайн генератор конфигов, мне во время эксперимента понадобились следующие параметры:

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

Остановлюсь подробней на параметре txindex=1. Если не включить этот параметр, то нода не сможет обращаться к входным и выходным параметрам транзакций, которые не относятся к кошельку ноды. Это может понадобиться, когда вы пытаетесь отправить повторную транзакцию с использованием того же входа, который по факту является ссылкой на выход внешней транзакции. Этот параметр потребует дополнительно порядка 20 GB дискового пространства под хранение индексированных данных.

Если у вас оригинальная нода, и вы хотите добавить пиры с включенным full-RBF, то в конфигурационный файл добавьте еще следующие параметры:

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

Список пиров с включенным full-RBF взят здесь.

Шаг 4. Запускаем ноду и создаем кошелек

Запускаем ноду при помощи команды ./bitcoind -daemon. Если вы не хотите запускать ноду в фоновом режиме, то запускайте без параметра -daemon

Дальше нода должна начать синхронизацию, у меня весь процесс занял порядка трое суток.

Обращаться к ноде можно при помощи bitcoin-cli. Например, посмотреть сколько уже скачено блоков можно следующей командой: ./bitcoin-cli getblockcount. Со всеми командами можно ознакомиться здесь.

После полной синхронизации необходимо создать кошелек. Это можно сделать разными способами (импортировать, сгенерировать), например, создать командой createwallet:

./bitcoin-cli createwallet "testwallet"

Шаг 5. Подготавливаем скрипт

Я использовал python-скрипты отсюда.

Для начала стоит убедиться, что вы можете обращаться к локальной Bitcoin ноде через python-bitcoinlib:

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

Дальше можно взять за основу doublespend.pyи сделать следующее:

  1. Отправить первую транзакцию с network fee значительно меньшим, чем у текущих транзакций в мемпуле. Так, транзакция «застрянет» в мемпуле и не попадет в блок;

  2. Подождать минуту, пока транзакция распространяется по сети;

  3. Отправить вторую транзакцию с network fee в разы превышающим текущих транзакций в мемпуле. Так, у майнера будет мотивация взять именно повторную транзакцию в блок.

Что в итоге получилось

Я проводил эксперимент несколько раз — результат был одинаков. Рассмотрим на примере одной из итераций:

Время создания

Network fee

Транзакция №1

00:00

0.0000113 BTC (0.26$)

Транзакция №2

00:19

0.004068 BTC (±94$)

Первую транзакцию я отправил с network fee = 0.26$. Это значительно ниже рыночных условий. Несмотря на то, что вторая транзакция имела fee в 94$, майнеры (создатели блоков) все равно ее не брали. То есть replace-by-fee не сработал.

Примечательно, как блокчеин эксплореры реагировали на повторные транзакции. В основном все отображали только первую транзакцию (например, mempool.space или blockchair). Эксплорер Blockcypher отображает повторные транзакции и предупреждает о double-spend:

Источник: https://live.blockcypher.com/Источник: https://live.blockcypher.com/

Я предполагаю, что майнеры не могут взять повторную транзакцию в блок, так как этот блок будет отвергнут большинством участников сети. И пока Bitcoin Core v24.0.1 с включенным full-RBF стоит у меньшинства участников, замена транзакций работать не будет.

Если вам понравилась статья, то подписывайтесь на мой телеграм канал, где я рассказываю про продакт-менеджмент, технологии и предпринимательство в крипте: @grin_channel

© Habrahabr.ru