sygcpp.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /**
  2. * Thanks PurpleI2P Project for support to writing that code.
  3. *
  4. * IRC: irc.ilita.i2p port 6667 || 303:60d4:3d32:a2b9::3 port 16667
  5. * general channels: #ru and #howtoygg
  6. *
  7. * git: notabug.org/acetone/SimpleYggGen-CPP
  8. *
  9. * developers: acetone, lialh4, orignal, R4SAS, Vort
  10. * developers team, 2020 (c) GPLv3
  11. *
  12. */
  13. #include <x86intrin.h>
  14. #include <string.h> // memcmp
  15. #include <sodium.h> // библиотека libsodium
  16. #include <iostream> // вывод на экран
  17. #include <string>
  18. #include <sstream>
  19. #include <fstream> // файловые потоки
  20. #include <iomanip> // форматированный вывод строк
  21. #include <bitset> // побитовое чтение
  22. #include <vector>
  23. #include <thread> // многопоточность
  24. #include <mutex>
  25. #include <chrono> // для вычисления скорости
  26. #include <ctime>
  27. #ifdef _WIN32 // преобразование в IPv6
  28. #include <ws2tcpip.h>
  29. #else
  30. #include <arpa/inet.h>
  31. #endif
  32. #include "x25519.h"
  33. #define BLOCKSIZE 10000
  34. //#define SELF_CHECK
  35. ////////////////////////////////////////////////// Заставка
  36. void intro()
  37. {
  38. std::cout <<
  39. std::endl <<
  40. " +--------------------------------------------------------------------------+" << std::endl <<
  41. " | SimpleYggGen C++ 3.0-Vort |" << std::endl <<
  42. " | magic and libsodium inside: x25519 -> sha512 |" << std::endl <<
  43. " | notabug.org/acetone/SimpleYggGen-CPP |" << std::endl <<
  44. " | |" << std::endl <<
  45. " | developers: Vort, acetone, R4SAS, lialh4, orignal |" << std::endl <<
  46. " | GPLv3 (c) 2020 |" << std::endl <<
  47. " +--------------------------------------------------------------------------+" << std::endl <<
  48. std::endl;
  49. }
  50. ////////////////////////////////////////////////// Суть вопроса
  51. std::mutex mtx;
  52. int conf_proc = 0;
  53. int conf_mode = 0;
  54. int conf_log = 0;
  55. int conf_high = 0;
  56. std::string conf_search;
  57. std::string log_file;
  58. std::time_t sygstartedin = std::time(NULL); // для вывода времени работы
  59. int countsize = 0; // определяет периодичность вывода счетчика
  60. uint64_t block_count = 0; // количество вычисленных блоков
  61. uint64_t totalcountfortune = 0; // счетчик нахождений
  62. std::chrono::steady_clock::duration blocks_duration(0);
  63. int config()
  64. {
  65. std::ifstream conffile ("sygcpp.conf");
  66. if(!conffile) // проверка наличия конфига
  67. {
  68. std::cout << " Configuration file not found..." << std::endl;
  69. conffile.close();
  70. std::ofstream newconf ("sygcpp.conf"); // создание конфига
  71. if(!newconf)
  72. {
  73. std::cerr << " Config (sygcpp.conf) creation failed :(" << std::endl;
  74. return -1;
  75. }
  76. newconf << "1 0 1 9 ::\n"
  77. << "| | | | ^Pattern for search by name.\n"
  78. << "| | | ^Start position for high addresses search.\n"
  79. << "| | ^Logging mode (0 - console output only, 1 - log to file).\n"
  80. << "| ^Mining mode (0 - by name, 1 - high address).\n"
  81. << "^Count of thread (mining streams).\n\n"
  82. << "Parameters are separated by spaces.";
  83. newconf.close();
  84. std::ifstream conffile ("sygcpp.conf");
  85. if(conffile)
  86. std::cout << " Config successfully created :)" << std::endl;
  87. config();
  88. return 0;
  89. } else {
  90. conffile >> conf_proc >> conf_mode >> conf_log >> conf_high >> conf_search;
  91. conffile.close();
  92. if(conf_mode > 1 || conf_mode < 0 || conf_log > 1 || conf_log < 0 || conf_high < 0) // проверка полученных значений
  93. {
  94. std::cerr << " Invalid config found! Check it:\n";
  95. if(conf_mode > 1 || conf_mode < 0)
  96. std::cerr << " - field #2 - mining mode: 0 or 1 only\n";
  97. if(conf_log > 1 || conf_log < 0)
  98. std::cerr << " - field #3 - logging mode: 0 or 1 only\n";
  99. if(conf_high < 0)
  100. std::cerr << " - field #4 - start position for high address search (default 9)\n";
  101. std::cerr << " Remove or correct sygcpp.conf and run SYG again."<< std::endl;
  102. return -2;
  103. }
  104. unsigned int processor_count = std::thread::hardware_concurrency(); // кол-во процессоров
  105. if (conf_proc > (int)processor_count)
  106. conf_proc = (int)processor_count;
  107. countsize = 800 << __bsrq(conf_proc);
  108. }
  109. // вывод конфигурации на экран
  110. std::cout << " Threads: " << conf_proc << ", ";
  111. if(conf_mode)
  112. std::cout << "search high addresses (" << conf_high << "), ";
  113. else
  114. std::cout << "search by name (" << conf_search << "), ";
  115. if(conf_log)
  116. std::cout << "logging to text file." << std::endl;
  117. else
  118. std::cout << "console log only." << std::endl;
  119. std::cout << std::endl;
  120. return 0;
  121. }
  122. void testoutput()
  123. {
  124. if(conf_log) // проверка включено ли логирование
  125. {
  126. if(conf_mode)
  127. log_file = "syg-high.txt";
  128. else
  129. log_file = "syg-byname.txt";
  130. std::ifstream test(log_file);
  131. if(!test) // проверка наличия выходного файла
  132. {
  133. test.close();
  134. std::ofstream output(log_file);
  135. output << "**************************************************************************\n"
  136. << "Change EncryptionPublicKey and EncryptionPrivateKey to your yggdrasil.conf\n"
  137. << "Windows: C:\\ProgramData\\Yggdrasil\\yggdrasil.conf\n"
  138. << "Debian: /etc/yggdrasil.conf\n\n"
  139. << "Visit HowTo.Ygg wiki for more information (russian language page):\n"
  140. << "http://[300:529f:150c:eafe::6]/doku.php?id=yggdrasil:simpleygggen_cpp\n"
  141. << "**************************************************************************\n";
  142. output.close();
  143. } else test.close();
  144. }
  145. }
  146. int getOnes(const unsigned char HashValue[crypto_hash_sha512_BYTES])
  147. {
  148. int lOnes = 0; // кол-во лидирующих единиц
  149. for (int i = 0; i < 32; ++i) // всего 32 байта, т.к. лидирующих единиц больше быть не может (32*8 = 256 бит, а ff = 255)
  150. {
  151. std::bitset<8> bits(HashValue[i]);
  152. for (int i = 7; i >= 0; --i)
  153. {
  154. if (bits[i] == 1) // обращение к i-тому элементу битсета
  155. ++lOnes;
  156. else
  157. return lOnes;
  158. }
  159. }
  160. return -1; // это никогда не случится
  161. }
  162. std::string getAddress(unsigned char HashValue[crypto_hash_sha512_BYTES])
  163. {
  164. // функция "портит" массив хэша, т.к. копирование массива не происходит
  165. int lErase = getOnes(HashValue) + 1; // лидирующие единицы и первый ноль
  166. bool changeit = false;
  167. int bigbyte = 0;
  168. for(int j = 0; j < lErase; ++j) // побитовое смещение
  169. {
  170. for(int i = 63; i >= 0; --i)
  171. {
  172. if(bigbyte == i+1) // предыдущий байт требует переноса
  173. changeit = true;
  174. if(HashValue[i] & 0x80)
  175. bigbyte = i;
  176. HashValue[i] <<= 1;
  177. if(changeit)
  178. {
  179. HashValue[i] |= 0x01;
  180. changeit = false;
  181. }
  182. }
  183. }
  184. uint8_t ipAddr[16];
  185. ipAddr[0] = 0x02;
  186. ipAddr[1] = lErase - 1;
  187. for (int i = 0; i < 14; ++i)
  188. ipAddr[i + 2] = HashValue[i];
  189. char ipStrBuf[46];
  190. inet_ntop(AF_INET6, ipAddr, ipStrBuf, 46);
  191. return std::string(ipStrBuf);
  192. }
  193. void logStatistics()
  194. {
  195. if (++block_count % countsize == 0)
  196. {
  197. auto timedays = (std::time(NULL) - sygstartedin) / 86400;
  198. auto timehours = ((std::time(NULL) - sygstartedin) - (timedays * 86400)) / 3600;
  199. auto timeminutes = ((std::time(NULL) - sygstartedin) - (timedays * 86400) - (timehours * 3600)) / 60;
  200. auto timeseconds = (std::time(NULL) - sygstartedin) - (timedays * 86400) - (timehours * 3600) - (timeminutes * 60);
  201. std::chrono::duration<double, std::milli> df = blocks_duration;
  202. blocks_duration = std::chrono::steady_clock::duration::zero();
  203. int khs = conf_proc * countsize * BLOCKSIZE / df.count();
  204. std::cout <<
  205. " kH/s: [" << std::setw(7) << std::setfill('_') << khs <<
  206. "] Total: [" << std::setw(19) << block_count * BLOCKSIZE <<
  207. "] Found: [" << std::setw(3) << totalcountfortune <<
  208. "] Uptime: " << timedays << ":" << std::setw(2) << std::setfill('0') <<
  209. timehours << ":" << std::setw(2) << timeminutes << ":" << std::setw(2) << timeseconds << std::endl;
  210. }
  211. }
  212. std::string keyToString(key25519 key)
  213. {
  214. std::stringstream ss;
  215. for (int i = 0; i < KEYSIZE; ++i)
  216. ss << std::setw(2) << std::setfill('0') << std::hex << (int)key[i];
  217. return ss.str();
  218. }
  219. void logKeys(std::string address, key25519 publicKey, key25519 privateKey)
  220. {
  221. std::cout << std::endl;
  222. std::cout << " Address: " << address << std::endl;
  223. std::cout << " PublicKey: " << keyToString(publicKey) << std::endl;
  224. std::cout << " PrivateKey: " << keyToString(privateKey) << std::endl;
  225. std::cout << std::endl;
  226. if (conf_log) // запись в файл
  227. {
  228. std::ofstream output(log_file, std::ios::app);
  229. output << std::endl;
  230. output << "Address: " << address << std::endl;
  231. output << "EncryptionPublicKey: " << keyToString(publicKey) << std::endl;
  232. output << "EncryptionPrivateKey: " << keyToString(privateKey) << std::endl;
  233. output.close();
  234. }
  235. }
  236. void process_fortune_key(const keys_block& block, int index)
  237. {
  238. if (index == -1)
  239. return;
  240. key25519 public_key;
  241. key25519 private_key;
  242. block.get_public_key(public_key, index);
  243. block.get_private_key(private_key, index);
  244. uint8_t sha512_hash[crypto_hash_sha512_BYTES];
  245. crypto_hash_sha512(sha512_hash, public_key, KEYSIZE);
  246. std::string address = getAddress(sha512_hash);
  247. logKeys(address, public_key, private_key);
  248. ++totalcountfortune;
  249. }
  250. template <int T>
  251. void miner_thread()
  252. {
  253. key25519 public_key;
  254. keys_block block(BLOCKSIZE);
  255. uint8_t random_bytes[KEYSIZE];
  256. uint8_t sha512_hash[crypto_hash_sha512_BYTES];
  257. for (;;)
  258. {
  259. auto start_time = std::chrono::steady_clock::now();
  260. int fortune_key_index = -1;
  261. randombytes(random_bytes, KEYSIZE);
  262. block.calculate_public_keys(random_bytes);
  263. for (int i = 0; i < BLOCKSIZE; i++)
  264. {
  265. block.get_public_key(public_key, i);
  266. crypto_hash_sha512(sha512_hash, public_key, KEYSIZE);
  267. if (T == 1) // high mining
  268. {
  269. int newones = getOnes(sha512_hash);
  270. if (newones > conf_high)
  271. {
  272. conf_high = newones;
  273. fortune_key_index = i;
  274. }
  275. }
  276. else // name mining
  277. {
  278. if (getAddress(sha512_hash).find(
  279. conf_search.c_str()) != std::string::npos)
  280. {
  281. fortune_key_index = i;
  282. break; // можно использовать только один ключ из блока
  283. }
  284. }
  285. }
  286. auto stop_time = std::chrono::steady_clock::now();
  287. mtx.lock();
  288. blocks_duration += stop_time - start_time;
  289. process_fortune_key(block, fortune_key_index);
  290. logStatistics();
  291. mtx.unlock();
  292. }
  293. }
  294. #ifdef SELF_CHECK
  295. void selfCheck()
  296. {
  297. std::cout << "Self-check started." << std::endl;
  298. for (int i = 0; i < 17; i++)
  299. {
  300. int block_size = 1 << i;
  301. keys_block block(block_size);
  302. uint8_t random_bytes[KEYSIZE];
  303. randombytes(random_bytes, KEYSIZE);
  304. block.calculate_public_keys(random_bytes);
  305. key25519 public_key1;
  306. key25519 public_key2;
  307. key25519 private_key;
  308. for (int j = 0; j < block_size; j++)
  309. {
  310. block.get_public_key(public_key1, j);
  311. block.get_private_key(private_key, j);
  312. crypto_scalarmult_curve25519_base(public_key2, private_key);
  313. if (memcmp(public_key1, public_key2, KEYSIZE) != 0)
  314. {
  315. std::cout << "!!! Self-check failed !!!" << std::endl;
  316. std::cout << " PrivateKey: " << keyToString(private_key) << std::endl;
  317. std::cout << " PublicKey1: " << keyToString(public_key1) << std::endl;
  318. std::cout << " PublicKey2: " << keyToString(public_key2) << std::endl;
  319. std::cout << "!!! Self-check failed !!!" << std::endl;
  320. return;
  321. }
  322. else
  323. {
  324. //std::cout << " Self-check ok" << std::endl;
  325. //std::cout << " PrivateKey: " << keyToString(private_key) << std::endl;
  326. }
  327. }
  328. }
  329. std::cout << "Self-check finished." << std::endl;
  330. }
  331. #endif
  332. // ------------------------------------------------------
  333. int main()
  334. {
  335. intro();
  336. #ifdef SELF_CHECK
  337. selfCheck();
  338. return 0;
  339. #endif
  340. int configcheck = config();
  341. if(configcheck < 0) // функция получения конфигурации
  342. {
  343. std::cerr << " Error code: " << configcheck << std::endl << std::endl;
  344. system("PAUSE");
  345. return configcheck;
  346. }
  347. testoutput();
  348. std::thread* lastThread;
  349. for (int i = 0; i < conf_proc; i++)
  350. lastThread = new std::thread(conf_mode ? miner_thread<1> : miner_thread<0>);
  351. lastThread->join();
  352. std::cerr << "SYG has stopped working unexpectedly! Please, report about this." << std::endl;
  353. system("PAUSE");
  354. return -420;
  355. }