Майнер Bitcoin на плате Марсоход3

 bitcoin

Сразу скажу, что какого-то уникального прорыва здесь нет.

Проект работает в плате Марсоход3, но получить какую либо выгоду с его помощью не получится - слишком мала производительность получившегося майнера. Для нас здесь интересны только используемые алгоритмы и принципы работы. Я расскажу как устроен майнер, что он делает, и как его запустить в плате Марсоход3, как реально начать майнинг с платой Марсоход3 и не заработать ничего.

Я заинтересовался майнером по нескольким причинам.
Во-первых меня замучила своими рассылками компания Intel. Однажды они прислали мне вот это:

intel adv
Что это такое? Интел интересуется блокчейнами? Вот это да!

Во-вторых, последнее время на разных технических сайтах отчего-то появилось много статей про блокчейны.

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

Итак, этот проект содержит исходники, собранные из разных открытых репозиториев и адаптированные для нашей платы марсоход3.
За основу был взят https://github.com/progranism/Open-Source-FPGA-Bitcoin-Miner.git В этом Open-Source-FPGA-Bitcoin-Miner на самом деле много под-проектов для разных плат, китов и микросхем ПЛИС.

Наиболее подходящий для нашей платы проект находится в папке Open-Source-FPGA-Bitcoin-Miner\projects\DE2_115_makomk_serial\

Конечно, этот дизайн вот прямо так нам не подходит. Плата DE2_115 содержит ПЛИС Cyclone IV с емкостью 115 тысяч логических элементов. У нас же на плате Марсоход3 есть Altera MAX10 с емкостью 50 тысяч логических элементов. Это меньше более чем в два раза (какая странная фраза..). Конечно, если просто в проекте сменить микросхему Cyclone IV на MAX10, то компиляция элементарно не помещается в ПЛИС. Выход нашелся простой: разработчик открытого проекта майнера уже позаботился о менее емких микросхемах. В настройках проекта есть предопределенный Verilog макрос CONFIG_LOOP_LOG2. Изменять его можно в настройках в проекте в среде САПР Intel Quartus Prime:

sha256 option

Этот макрос определает насколько "параллельно" будет выполняться вычисление. Основная рабочая лошадка алгоритма поиска блока для биткоина - это алгоритм SHA256 использующийся для вычисления хэша блока данных. В алгоритме SHA256 есть 64 однотипных операции, называемые раундами. Эти операции можно развернуть в единую цепочку действий. Тогда весь алгоритм SHA256 может быть выполнен за один такт рабочей частоты. При этом будет занято много логики в ПЛИС. Если места в микросхеме мало, то можно пожертвовать скоростью вычислений и оставить только половину цепочки, но пропускать через нее данные два раза. Тогда, условно говоря, весь алгоритм выполнится не за один, а за два такта рабочей частоты. Будет в два раза медленнее.

Вот макрос CONFIG_LOOP_LOG2 определяет насколько цепочка/pipeline SHA256 будет развернут.
Если CONFIG_LOOP_LOG2 = 0, то в Cyclone IV 115 тыс. логических элементов SHA256 будет полностью развернут. Весь проект будет занимать где-то под 76 тыс логических элементов. Если CONFIG_LOOP_LOG2 = 1, то SHA256 будет развернут только на половину. Нашей ПЛИС MAX10 50 тыс. логических элементов весь проект будет занимать где-то около 35 тыс логических элементов. Можно указать CONFIG_LOOP_LOG2 = 2 или 3 и свернуть, укоротить pipeline SHA256 еще сильнее - тогда проект станет еще меньше и еще медленнее. Так, я обнаружил проект майнера биткоинов, который работает в плате BeMicro c Cyclone IV 22 тыс. логических элементов. То есть уместить проект можно даже в маленькую ПЛИС, только будет работать гораздо медленнее.

В процессе разбора алгоритма поиска биткоина я обнаружил совершенно потрясающую статью, которая объясняет как происходит поиск нужного блока. Эта статья с хабра "Майним Bitcoin с помощью бумаги и ручки" (конечно перевод). Пересказывать статью пожалуй нет смысла - лучше почитать. Я же просто покажу некоторые фрагменты кода майнера на Verilog и проиллюстрирую его.

Вот, например, блок схема, которая описывает один раунд алгоритма SHA256:

sha256 digester

Тут же на рисунке я показал, как этот раунд описывается в Verilog модуле sha256_digester. Сравнивая блок схему и код Verilog можно понять где, что и как происходит.
Раунд принимает 256 бит данных, оформленных в виде 8-ми 32-х битных слов. Эти данные обрабатываются с помощью операций, отмеченных в синих блоках.

Функция большинства (Ma блок) побитово работает со словами A, B и C.
Для каждой битовой позиции она возвращает 0, если большинство входных битов в этой позиции — нули, иначе вернёт 1.

module maj (x, y, z, o);
 input [31:0] x, y, z;
 output [31:0] o;
 assign o = (x & y) | (z & (x | y));
endmodule

Блок Σ0 циклически сдвигает A на 2 бита, затем исходное слово A циклически сдвигается на 13 бит, и, аналогично, на 22 бита. Получившиеся три сдвинутые версии A побитово складываются по модулю 2 (обычный xor, (A ror 2) xor (A ror 13) xor (A ror 22)).

module e0 (x, y);
  input [31:0] x;
  output [31:0] y;
  assign y = {x[1:0],x[31:2]} ^ {x[12:0],x[31:13]} ^ {x[21:0],x[31:22]};
endmodule

Σ1 по структуре аналогичен Σ0, но работает со словом E, и имеет другие сдвиговые константы — 6, 11 и 25.

module e1 (x, y);
  input [31:0] x;
  output [31:0] y;
  assign y = {x[5:0],x[31:6]} ^ {x[10:0],x[31:11]} ^ {x[24:0],x[31:25]};
endmodule

Ch реализует функцию выбора. На каждой битовой позиции проверяется бит из E, если он равен единице, то на выход идёт бит из F с этой позиции, иначе бит из G. Таким образом, биты из F и G перемешиваются, исходя из значения E.

module ch (x, y, z, o);
  input [31:0] x, y, z;
  output [31:0] o;
  assign o = z ^ (x & (y ^ z));
endmodule

На блок схеме красными квадратами обозначена функция суммирования слов, я провел зеленые стрелки на рисунке выше от некоторых сумматоров к операторам "плюс" в Verilog представлении алгоритма.

Как я уже писал выше, алгоритм SHA256 содержит 64 таких раунда, то есть, для максимальной скорости вычислений таких блоков sha256_digest нужно установить в цепочку 64 штуки.

sha256 pipeline
Здесь я изобразил только 4 блока-раунда. Видно, что некоторые слова из одного раунда в другой переходят без изменений. Так, слово G из первого раунда переходит в слово H второго раунда. Слово F первого раунда переходит без изменений в слово G второго раунда b и, затем, в слово H третьего раунда. Понятно, что в pipeline на границе раундов нужны регистры, чтобы данные синхронно двигались от раунда к раунду. В проекте в качестве этих дополнительных регистров устанавливаются модули shifter_32b. Некоторые из них реализованы в RAM блоках ПЛИС, а именно с помощью мегафункции Альтеры altshift_taps.

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

Если посмотреть всю иерархию проекта, то видно, насколько проект сложен и сколько в нем логики и модулей. Вот только фрагмент иерархии проекта:

hier

Модуль serial_receive получает вычислительную задачу из ПК. Это блок данных к которому нужно путем подбора специального поля nonce вычислить хэш и если повезет и хэш будет удовлетворять особому условию, то блок будет принят и использован при формировании монетки bitcoin. Если удастся подобрать золотой nonce - то он отправляется назад в ПК так же по последовательному интерфейсу через модуль serial_transmit.

Два последовательных вычислителя SHA256 - это чтоб жизнь медом не казалась, чтоб считать было не трудно, а очень трудно. Итого 64+64 => должно быть 128 раундов sha256_digester. Но поскольку места в моей ПЛИС мало, то приходится использовать CONFIG_LOOP_LOG=1 и вдвое терять в производительности, так что у меня цепочка дайджестеров только 64 раундов. Ну еще понятно дополнительные shifter_32b и всякие sha256_update_w - это вычислители дополнительных констант W.

Конечно, в проекте есть PLL, который задает тактовую частоту для всех схемы. Скажу, что тактовая частота у меня не высокая, всего 25МГц. Это из-за того, что я взял готовый модуль приемопередатчика последовательного порта с сайта fpga4fun - почему-то в github проекте его не оказалось, но в readme было указание где брать модуль. А модуль этого последовательного порта требует 25МГц для стандартной частоты порта 115200bps. Мой прогноз по быстродействию этого майнера - около 10MH/sec (мегахэшей в секунду), так как условно говоря за один такт считаем один SHA256, но pipeline в два раза меньше чем нужно, значит и скорость вычислений будет не 25MH/sec, а в 2 раза меньше, ну где-то 12,5-10MH/sec. Если бы развернуть весь SHA256, да запустить на частоте хотя бы 100MHz, то производительность была бы 100MH/sec.

Причем, нужно заметить, что скорость работы майнера не зависит от скорости последовательного порта. Почти не зависит. Через последовательный порт мы просто получаем блок данных к которому нужно путем многократного перебора и изменения/подбора поля nonce в структуре данных вычислить хэш и проверить получился ли он такой как нужно, удовлетворяет ли он особому условию: старшие 32 бита хеша должны быть равны нулю.

Таким образом, я использую всего 25МГц тактовую частоту и честно говоря боюсь подавать больше - сильно греется MAX10.

Дальше расскажу, как запустить майнинг.

Сперва нужно найти себе пул для майнинга. Как я понимаю вероятность добыть биткоин последнее время очень мала и поэтому майнеры объединяются в группы майнеров, чтобы сообща копать и делить найденное на всех, пропорционально вкладу каждого. Я попробовал подключиться к пулу https://slushpool.com Там нужно зарегистрироваться, то есть создать аккаунт и в принципе можно начинать.

Нужна программа для майнинга - она у меня есть - это программа на питоне miner.py. Писал ее не я (а некий "teknohog"), как точно работает не знаю, но должна бы работать вот так: 

1) в тексте программы указан URL пула майнеров и номер порта на котором работать, а так же имя пользователя, который копает монетки;

2) программа запускается и подключается через интернет к пулу, получая оттуда задания на вычисление с помощью протокола "getwork";

3) задание формируется в виде пакета данных, которые передаются через последовательный порт в FPGA плату для поиска нужного golden nonce;

4) найденные nonce отправляются назад из платы через последовательный порт к программе майнера;

5) программа отправляет результат на пул, где теоретически начиcляются "найденные богатства".

Программа на питоне требует дополнительных библиотек, а именно PySerial и jsonrpc. Они есть в моем репозитории, в питоне нужно их установить, прежде чем запускать майнер.

Есть еще проблема: в настоящее время пули не работают через протокол getwork, а работают через какие-то другие протоколы. getwork считается устаревшим. Выход из этой ситуации - это запуст прокси сервера. Я скачал с сайта slashpool.com их собственный прокси сервер mining_proxy.exe

Запускаю его - это консольная программа. В питоновском скрипте у меня вот такие параметры:

user = "FpgaMiner123.worker1"
password = "x"
host = "localhost"
http_port = "8332"

serial_port = "COM6"

Вы можете использовать такие же параметры, как и я. Тогда все что вы накопаете попадет на мой БТЦ счет на слашпуле.
Шучу. Ничего вы не накопаете.. слишком медленно работает наш майнер.

mining

Вот фоточка, как мой майнер работает..

Весь проект можно будет взять на github: https://github.com/marsohod4you/btc-fpga-miner

 

 

 


Добавить комментарий