Создание биткойн-майнера на Java

Биткойн майнер на Java

Большой рост цен на игровые видеокарты (сравните цены декабря 2017-го и февраля 2018-го, почувствуйте разницу) говорит о том, что предприимчивый пользователь не очень верит в падение курса биткойна. Но даже в такой холодной стране с дешевым электричеством, как Россия, себестоимость майнинга одного намайненного битка, с учетом риска дальнейшего падения и затруднений при обналичивании, не совсем себя оправдывает. Что же делать в такой ситуации? Как обычно — задействовать чужие компьютеры, переходить к распределенному майнингу, освобождать от тяжелой работы свою личную видеокарту, заварить чашку кофе и откинуться на спинку кресла.

Рекомендуем к прочтению: Как запустить свое ICO

Выбор криптовалюты и подготовка

В качестве криптовалюты мы выбрали биткойны — из-за их высокой стоимости и отличной (по сравнению с друигими криптовалютами) документации. Так как сеть биткойн не владеет централизованым хранилищем данных, чтобы с ней работать, нам потребуются средства синхронизации с другими узлами сети. К счастью, уже есть готовое решение — пакет программ Bitcoin Core. Синхронизация с живой сетью занимает очень много времени и места на диске, поэтому для начала разработки и тестирования лучше использовать тестовую сеть testnet, которую периодически очищают от информации о транзакциях. Итак, запускаем UI-приложение Bitcoin Core (testnet) и подождем, пока синхронизация закончится. В дальнейшем для работы будем использовать консольный сервис bitcoind.

Для общения с bitcoind используется протокол JSON-RPC. Это очень простой протокол поверх HTTP, который позволяет вызывать методы сервера, используя JSON, чтобы задавать имя метода и параметры.

По умолчанию в целях безопасности возможность подключения к bitcoind отключена. Чтобы ее включить, нужно создать файл bitcoin.conf в каталоге Windows: %APPDATA%\Bitcoin\ (например, C:\Users\username\AppData\Roaming\Bitcoin\bitcoin.conf) или Linux: $HOME/.bitcoin/ (например, /home/username/.bitcoin/bitcoin.conf). Готовый файл можно взять с GitHub. Находим в нем и редактируем следующие параметры:

Чтобы проверить настройки, можно воспользоваться готовым клиентом bitcoin-cli. Например, выполнив команду getinfo (предварительно запустив bitcoind). Подробное описание всех команд можно посмотреть тут.

биткоин майнер

Наш JSON-RPC-клиент напишем, используя фреймворк Vert.x, потому что он простой, код занимает мало места и в нем реализованы все необходимые нам функции.

Итак, создаем HTTP-клиент. Bitcoind использует базовую аутентификацию, поэтому конвертируем в Base64 строку с логином и паролем.

Пишем простой метод для вызова методов bitcoind. Будем передавать в него команду в JSON-формате и handler, чтобы реагировать на полученный ответ от сервера.

Основные команды, которые нам понадобятся, — это получить работу и отправить работу. Но прежде чем приступать к их реализации, рассмотрим подробнее процесс майнинга. Как известно, биткойн базируется на цепочке блоков, в которых хранится информация обо всех транзакциях. Каждый блок состоит из заголовка и списка транзакций. Задача майнера — получить хеш заголовка блока, значение которого меньше заданного. За это он вознаграждается некоторой суммой криптоденег.

Заголовок состоит из нескольких полей:

  • версия (определяет версию валидации блока),
  • хеш заголовка предыдущего блока,
  • корень Меркле (хеш всех транзакций, включенных в блок),
  • время создания блока,
  • bits (закодированная версия заданного максимального значения хеша блока),
  • nonce (произвольное значение).
биткоин майнер java
Расшифровка заголовка

Всю эту информацию позволяет получить команда getblocktemplate.

В результате получим JSON-объект.

Чтобы добиться нужного значения хеша заголовка, майнер может менять nonce и время создания блока (в ограниченном диапазоне). Размерность nonce и ограничения на изменения времени создания блока приводят к ограниченному диапазону перебора возможных значений. Чтобы его увеличить, предусмотрена возможность изменения транзакций, в результате чего меняется корень Меркле, увеличивая тем самым варианты перебора. Задача пула — распределить работу между майнерами таким образом, чтобы их работа не дублировалась.

Первой транзакцией в блоке обычно идет так называемая coinbase-транзакция, которая отвечает за генерацию новых денег. Она отличается от обычной транзакции тем, что не имеет входа, описывающего, откуда пришли деньги. Кроме того, в каждой транзакции есть поля scriptPubKey и scriptSig. В них содержится небольшая программа на языке Script, которая отвечает за валидацию транзакции. Чтобы транзакция считалась валидной, вызывается сначала scriptSig из старой транзакции, а затем scriptPubKey из новой транзакции. Если выполнение успешно, то транзакция считается валидной. Так как в coinbase-транзакции нет входящей транзакции, то поле scriptSig называется coinbase и в него можно писать любую информацию. Этим и пользуются пулы, чтобы увеличить диапазон перебираемых значений.

биткоин майнер
Описание полей coinbase-транзакции

Разработчики Bitcoin немного перемудрили с представлением данных — то прямой, то обратный порядок байтов, поэтому, чтобы не сойти с ума, воспользуемся для генерации coinbase-транзакции Java-библиотекой bitcoinj.

Для удобства майнеров (чтобы им лишний раз не делать вычисления) разделим coinbase-транзакцию на три части: coinbase1, extranonce, coinbase2.

Mining Pool Java

Осталось обеспечить канал связи с майнерами. Для этого воспользуемся протоколом Stratum. Он базируется на TCP/IP-сокетах, через которые гоняются данные в формате JSON. Создадим обработчик соединения с майнерами.

Протокол требует авторизации майнеров, а так как наши майнеры не совсем люди и никак не могут зарегистрироваться, можно логин генерировать, пароль же либо зашить в исходный код майнера, либо вычислять по известному пулу и майнеру алгоритму. Подробнее о протоколе Stratum можно почитать тут. Чтобы гарантированно распределять уникальную часть работы каждому майнеру, разделим extranonce на две части и в первой будем проставлять счетчик майнеров, а вторую разрешим изменять.

Информацию об extranonce и уникальный идентификатор подписки отправляем клиенту в ответ на команду mining.subscribe:

Сформируем задание для майнера.

Когда майнер найдет решение, он пришлет вторую часть extranonce, время создания блока и nonce. Пулу необходимо собрать новый блок и отправить его в bitcoin-сеть.

Когда блок успешно добавлен, нужно уведомить всех клиентов об отмене работы над этим блоком. Для этого используем шину событий.

Рекомендуем к прочтению: Лучшие ICO-компании

Биткойн майнер готов!

Наш проект завершен. Осталось добавить обработку ошибок, и можно начинать майнить. Однако помните, что пул для майнинга требует хорошего канала и довольно много места на диске. И не забудьте предупредить об этих ограничениях друзей, которые добровольно согласятся вам помочь в майнинге криптовалюты, ведь вы не хотите ненароком их огорчить?

Понравилась статья? Поделиться с друзьями:
Добавить комментарий