libssplus.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  1. /*
  2. * Copyright 2016 Mikeqin <Fengling.Qin@gmail.com>
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 3 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include <stdbool.h>
  10. #include <stdint.h>
  11. #include <string.h>
  12. #include <pthread.h>
  13. #include <sys/stat.h>
  14. #include <fcntl.h>
  15. #include <unistd.h>
  16. #include <sys/mman.h>
  17. #include "sha2.h"
  18. #include "libssplus.h"
  19. #define INSTRUCTIONS_RAM_START 0x42000000
  20. #define INSTRUCTIONS_RAM_SIZE (1 << 16)
  21. #define POINTS_RAM_START 0xfffc0000
  22. #define POINTS_RAM_SIZE (256 << 10)
  23. /* hasher instructions */
  24. #define INST_DONE 0x00040000
  25. #define INST_DATA_IRAM 0x0
  26. #define INST_DATA_LASTHASH_PAD 0x14000000
  27. #define INST_DATA_LASTHASH_IRAM 0x10000000
  28. #define INST_DATA_PAD512 0x26000000
  29. #define INST_MID_INIT 0x0
  30. #define INST_MID_LASTHASH 0x100000
  31. #define NEXT_ADDR(x) (((x) & 0x1ff) << 8)
  32. #define UNPACK32(x, str) \
  33. { \
  34. *((str) + 3) = (uint8_t) ((x) ); \
  35. *((str) + 2) = (uint8_t) ((x) >> 8); \
  36. *((str) + 1) = (uint8_t) ((x) >> 16); \
  37. *((str) + 0) = (uint8_t) ((x) >> 24); \
  38. }
  39. #define SORTER_DEBUG
  40. struct ssp_hasher_instruction {
  41. uint32_t opcode;
  42. uint8_t data[64];
  43. };
  44. struct ssp_point {
  45. uint32_t nonce2;
  46. uint32_t tail;
  47. };
  48. struct ssp_info {
  49. pthread_t hasher_thr;
  50. pthread_mutex_t hasher_lock;
  51. volatile uint32_t *iram_addr;
  52. volatile uint64_t *pram_addr;
  53. bool stratum_update;
  54. bool run;
  55. };
  56. struct ssp_pair_element {
  57. uint32_t nonce2[2];
  58. struct ssp_pair_element *next;
  59. };
  60. struct ssp_hashtable {
  61. struct ssp_point *cells;
  62. uint32_t size;
  63. uint32_t max_size; /* must be powers of 2 */
  64. uint32_t limit; /* probing limit */
  65. uint32_t c1;
  66. uint32_t c2;
  67. };
  68. static struct ssp_info sspinfo;
  69. static struct ssp_hashtable *ssp_ht = NULL;
  70. static struct ssp_pair_element *ssp_pair_head = NULL;
  71. static struct ssp_pair_element *ssp_pair_tail = NULL;
  72. #ifdef SORTER_DEBUG
  73. static uint32_t pair_count = 0;
  74. static uint32_t consumed = 0;
  75. static uint32_t discarded = 0;
  76. static uint32_t calls = 0;
  77. static struct timeval ssp_ti, ssp_tf;
  78. static double insert_time = .0;
  79. static uint32_t maxnonce = 0;
  80. static uint32_t ver = 0;
  81. #endif
  82. static void ssp_sorter_insert(const struct ssp_point *point)
  83. {
  84. uint32_t i;
  85. uint32_t key;
  86. #ifdef SORTER_DEBUG
  87. if (calls == 0xffffffff)
  88. applog(LOG_NOTICE, "calls overflow");
  89. calls++;
  90. #endif
  91. for (i = 0; i < ssp_ht->limit; i++) {
  92. key = (point->tail + ssp_ht->c1 * i + ssp_ht->c2 * i * i) %
  93. (ssp_ht->max_size);
  94. if (ssp_ht->cells[key].nonce2 == 0 && ssp_ht->cells[key].tail == 0) {
  95. /* insert */
  96. ssp_ht->cells[key].tail = point->tail;
  97. ssp_ht->cells[key].nonce2 = point->nonce2;
  98. ssp_ht->size++;
  99. goto out;
  100. }
  101. if (ssp_ht->cells[key].tail == point->tail) {
  102. /* get a collision */
  103. ssp_pair_tail->nonce2[0] = point->nonce2;
  104. ssp_pair_tail->nonce2[1] = ssp_ht->cells[key].nonce2;
  105. ssp_pair_tail->next = (struct ssp_pair_element *)cgmalloc(sizeof(struct ssp_pair_element));
  106. ssp_pair_tail = ssp_pair_tail->next;
  107. #ifdef SORTER_DEBUG
  108. pair_count++;
  109. #endif
  110. /* update nonce2 of the point */
  111. ssp_ht->cells[key].nonce2 = 0;
  112. ssp_ht->cells[key].tail = 0;
  113. /* or just delete it? */
  114. /* or leave it be? */
  115. goto out;
  116. }
  117. }
  118. /* discard */
  119. #ifdef SORTER_DEBUG
  120. discarded++;
  121. #endif
  122. out:
  123. return;
  124. }
  125. void ssp_sorter_init(uint32_t max_size, uint32_t limit, uint32_t c1, uint32_t c2)
  126. {
  127. #ifdef SORTER_DEBUG
  128. cgtime(&ssp_ti);
  129. #endif
  130. ssp_ht = (struct ssp_hashtable *)cgmalloc(sizeof(struct ssp_hashtable));
  131. ssp_ht->max_size = max_size;
  132. ssp_ht->limit = limit;
  133. ssp_ht->c1 = c1;
  134. ssp_ht->c2 = c2;
  135. ssp_ht->size = 0;
  136. ssp_ht->cells = (struct ssp_point *)cgmalloc(sizeof(struct ssp_point) * max_size);
  137. memset(ssp_ht->cells, 0, sizeof(struct ssp_point) * max_size);
  138. ssp_pair_head = (struct ssp_pair_element *)cgmalloc(sizeof(struct ssp_pair_element));
  139. ssp_pair_tail = ssp_pair_head;
  140. }
  141. void ssp_sorter_flush(void)
  142. {
  143. #ifdef SORTER_DEBUG
  144. double delta_t;
  145. cgtime(&ssp_tf);
  146. delta_t = tdiff(&ssp_tf, &ssp_ti);
  147. applog(LOG_NOTICE, "Stratum %d: %f s", ver, delta_t);
  148. applog(LOG_NOTICE, "Stratum %d: get %d pairs. %f pair/s", ver, pair_count, pair_count / delta_t);
  149. applog(LOG_NOTICE, "Stratum %d: consume %d pairs. %f pair/s", ver, consumed, consumed / delta_t);
  150. applog(LOG_NOTICE, "Stratum %d: discard %d points. %f point/s", ver, discarded, discarded / delta_t);
  151. applog(LOG_NOTICE, "Stratum %d: reading discards %d points. %f point/s. %.2f%%", ver, maxnonce - calls, (maxnonce - calls) / delta_t, (maxnonce - calls) * 1.0 / maxnonce * 100);
  152. applog(LOG_NOTICE, "Stratum %d: record %d points. %f%% of hashtable. %f point/s", ver, ssp_ht->size, ssp_ht->size * 100.0 / ssp_ht->max_size, ssp_ht->size / delta_t);
  153. applog(LOG_NOTICE, "Stratum %d: %d calls of sorter_insert. %f call/s", ver, calls, calls / delta_t);
  154. applog(LOG_NOTICE, "Stratum %d: avg call time - %f us", ver, delta_t * 1000000 / calls);
  155. applog(LOG_NOTICE, "Stratum %d: k^2 / 2N / pair - %f", ver, 0.5 * calls * calls / 4294967296 / pair_count);
  156. applog(LOG_NOTICE, "========================================================");
  157. cgtime(&ssp_ti);
  158. pair_count = 0;
  159. consumed = 0;
  160. discarded = 0;
  161. calls = 0;
  162. insert_time = 0;
  163. ver++;
  164. #endif
  165. ssp_ht->size = 0;
  166. memset(ssp_ht->cells, 0, sizeof(struct ssp_point) * ssp_ht->max_size);
  167. /* MM only use one stratum, we need drop all pairs */
  168. while (ssp_pair_head != ssp_pair_tail) {
  169. struct ssp_pair_element *tmp;
  170. tmp = ssp_pair_head;
  171. ssp_pair_head = tmp->next;
  172. free(tmp);
  173. }
  174. }
  175. int ssp_sorter_get_pair(ssp_pair pair)
  176. {
  177. struct ssp_pair_element *tmp;
  178. mutex_lock(&(sspinfo.hasher_lock));
  179. if (ssp_pair_head == ssp_pair_tail) {
  180. mutex_unlock(&(sspinfo.hasher_lock));
  181. return 0;
  182. }
  183. tmp = ssp_pair_head;
  184. pair[0] = tmp->nonce2[0];
  185. pair[1] = tmp->nonce2[1];
  186. ssp_pair_head = tmp->next;
  187. free(tmp);
  188. #ifdef SORTER_DEBUG
  189. consumed++;
  190. #endif
  191. mutex_unlock(&(sspinfo.hasher_lock));
  192. return 1;
  193. }
  194. static void *ssp_hasher_thread(void *userdata)
  195. {
  196. uint32_t last_nonce2 = 0, point_index = 0, nonce2;
  197. bool valid_nonce2 = false;
  198. struct ssp_info *p_ssp_info = (struct ssp_info *)userdata;
  199. while (1) {
  200. mutex_lock(&(sspinfo.hasher_lock));
  201. if (!p_ssp_info->run)
  202. valid_nonce2 = false;
  203. if (p_ssp_info->stratum_update) {
  204. p_ssp_info->stratum_update = false;
  205. point_index = 0;
  206. last_nonce2 = 0;
  207. valid_nonce2 = false;
  208. ssp_sorter_flush();
  209. applog(LOG_NOTICE, "libssplus: stratum update");
  210. }
  211. /* Note: hasher is fast enough, so the new job will start with a lower nonce2 */
  212. nonce2 = (sspinfo.pram_addr[point_index] & 0xffffffff);
  213. if (last_nonce2 > nonce2)
  214. valid_nonce2 = true;
  215. point_index = (point_index + 1) % (POINTS_RAM_SIZE / sizeof(struct ssp_point));
  216. if (valid_nonce2) {
  217. #ifdef SORTER_DEBUG
  218. if (nonce2 > maxnonce)
  219. maxnonce = nonce2;
  220. #endif
  221. ssp_sorter_insert((struct ssp_point *)&sspinfo.pram_addr[point_index]);
  222. }
  223. last_nonce2 = nonce2;
  224. mutex_unlock(&(sspinfo.hasher_lock));
  225. }
  226. return NULL;
  227. }
  228. static inline void ssp_hasher_fill_iram(struct ssp_hasher_instruction *p_inst, uint32_t inst_index)
  229. {
  230. uint8_t i;
  231. volatile uint32_t *p_iram_addr;
  232. uint32_t tmp;
  233. p_iram_addr = sspinfo.iram_addr + inst_index * 32;
  234. p_iram_addr[0] = p_inst->opcode;
  235. simplelog(LOG_DEBUG, "iram[%d*32+0] = 0x%08x;", inst_index, p_inst->opcode);
  236. for (i = 0; i < 16; i++) {
  237. tmp = ((p_inst->data[i * 4 + 0] << 24) |
  238. (p_inst->data[i * 4 + 1] << 16) |
  239. (p_inst->data[i * 4 + 2] << 8) |
  240. (p_inst->data[i * 4 + 3]));
  241. p_iram_addr[i + 1] = tmp;
  242. simplelog(LOG_DEBUG, "iram[%d*32+%d] = 0x%08x;", inst_index, i + 1, tmp);
  243. }
  244. p_iram_addr[i + 1] = 0x1; /* flush */
  245. simplelog(LOG_DEBUG, "iram[%d*32+%d] = 1;", inst_index, i + 1);
  246. }
  247. static inline void ssp_hasher_stop(void)
  248. {
  249. sspinfo.iram_addr[31] = 1;
  250. sspinfo.run = false;
  251. }
  252. static inline void ssp_hasher_start(void)
  253. {
  254. sspinfo.iram_addr[31] = 0;
  255. sspinfo.run = true;
  256. }
  257. int ssp_hasher_init(void)
  258. {
  259. int memfd;
  260. memfd = open("/dev/mem", O_RDWR | O_SYNC);
  261. if (memfd < 0) {
  262. applog(LOG_ERR, "libssplus: failed open /dev/mem");
  263. return 1;
  264. }
  265. sspinfo.iram_addr = (volatile uint32_t *)mmap(NULL, INSTRUCTIONS_RAM_SIZE,
  266. PROT_READ | PROT_WRITE,
  267. MAP_SHARED, memfd,
  268. INSTRUCTIONS_RAM_START);
  269. if (sspinfo.iram_addr == MAP_FAILED) {
  270. close(memfd);
  271. applog(LOG_ERR, "libssplus: mmap instructions ram failed");
  272. return 1;
  273. }
  274. sspinfo.pram_addr = (volatile uint64_t *)mmap(NULL, POINTS_RAM_SIZE,
  275. PROT_READ | PROT_WRITE,
  276. MAP_SHARED, memfd,
  277. POINTS_RAM_START);
  278. if (sspinfo.pram_addr == MAP_FAILED) {
  279. close(memfd);
  280. applog(LOG_ERR, "libssplus: mmap points ram failed");
  281. return 1;
  282. }
  283. close(memfd);
  284. if (pthread_create(&(sspinfo.hasher_thr), NULL, ssp_hasher_thread, &sspinfo)) {
  285. applog(LOG_ERR, "libssplus: create thread failed");
  286. return 1;
  287. }
  288. sspinfo.stratum_update = false;
  289. ssp_hasher_stop();
  290. mutex_init(&sspinfo.hasher_lock);
  291. return 0;
  292. }
  293. static inline void sha256_prehash(const unsigned char *message, unsigned int len, unsigned char *digest)
  294. {
  295. int i;
  296. sha256_ctx ctx;
  297. sha256_init(&ctx);
  298. sha256_update(&ctx, message, len);
  299. for (i = 0; i < 8; i++)
  300. UNPACK32(ctx.h[i], &digest[i << 2]);
  301. }
  302. void ssp_hasher_update_stratum(struct pool *pool, bool clean)
  303. {
  304. struct ssp_hasher_instruction inst;
  305. uint32_t coinbase_len_posthash, coinbase_len_prehash;
  306. uint32_t i, len_rem, block_nb;
  307. int merkle_index;
  308. uint32_t inst_index = 0, nonce2_init = 0;
  309. uint64_t coinbase_len_bits = pool->coinbase_len * 8;
  310. mutex_lock(&(sspinfo.hasher_lock));
  311. ssp_hasher_stop();
  312. /* instruction init */
  313. inst.opcode = 0;
  314. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  315. inst.data[28] = (nonce2_init >> 24) & 0xff;
  316. inst.data[29] = (nonce2_init >> 16) & 0xff;
  317. inst.data[30] = (nonce2_init >> 8) & 0xff;
  318. inst.data[31] = (nonce2_init) & 0xff;
  319. coinbase_len_prehash = pool->nonce2_offset - (pool->nonce2_offset % SHA256_BLOCK_SIZE);
  320. sha256_prehash(pool->coinbase, coinbase_len_prehash, inst.data + 32);
  321. ssp_hasher_fill_iram(&inst, inst_index);
  322. inst_index++;
  323. /* coinbase */
  324. coinbase_len_posthash = pool->coinbase_len - coinbase_len_prehash;
  325. block_nb = coinbase_len_posthash / SHA256_BLOCK_SIZE;
  326. len_rem = (coinbase_len_posthash % SHA256_BLOCK_SIZE);
  327. for (i = 0; i < block_nb; i++) {
  328. inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
  329. if (!i) {
  330. inst.opcode |= (63 - (pool->nonce2_offset % SHA256_BLOCK_SIZE));
  331. inst.opcode |= INST_MID_INIT;
  332. } else
  333. inst.opcode |= INST_MID_LASTHASH;
  334. memcpy(inst.data, pool->coinbase + coinbase_len_prehash + i * SHA256_BLOCK_SIZE, SHA256_BLOCK_SIZE);
  335. ssp_hasher_fill_iram(&inst, inst_index);
  336. inst_index++;
  337. }
  338. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  339. inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
  340. if (!block_nb) {
  341. inst.opcode |= (63 - (pool->nonce2_offset % SHA256_BLOCK_SIZE));
  342. inst.opcode |= INST_MID_INIT;
  343. } else
  344. inst.opcode |= INST_MID_LASTHASH;
  345. memcpy(inst.data, pool->coinbase + coinbase_len_prehash + (block_nb * SHA256_BLOCK_SIZE), len_rem);
  346. inst.data[len_rem] = 0x80;
  347. if (len_rem <= (SHA256_BLOCK_SIZE - 9)) {
  348. for (i = 0; i < 8; i++)
  349. inst.data[63 - i] = (coinbase_len_bits >> (i * 8)) & 0xff;
  350. ssp_hasher_fill_iram(&inst, inst_index);
  351. inst_index++;
  352. } else {
  353. ssp_hasher_fill_iram(&inst, inst_index);
  354. inst_index++;
  355. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  356. inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
  357. inst.opcode |= INST_MID_LASTHASH;
  358. for (i = 0; i < 8; i++)
  359. inst.data[63 - i] = (coinbase_len_bits >> (i * 8)) & 0xff;
  360. ssp_hasher_fill_iram(&inst, inst_index);
  361. inst_index++;
  362. }
  363. /* double hash coinbase */
  364. inst.opcode = INST_DATA_LASTHASH_PAD | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
  365. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  366. ssp_hasher_fill_iram(&inst, inst_index);
  367. inst_index++;
  368. /* merkle branches */
  369. for (merkle_index = 0; merkle_index < pool->merkles; merkle_index++) {
  370. inst.opcode = INST_DATA_LASTHASH_IRAM | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
  371. memcpy(inst.data + 32, pool->swork.merkle_bin[merkle_index], 32);
  372. ssp_hasher_fill_iram(&inst, inst_index);
  373. inst_index++;
  374. inst.opcode = INST_DATA_PAD512 | INST_MID_LASTHASH | NEXT_ADDR(inst_index + 1);
  375. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  376. ssp_hasher_fill_iram(&inst, inst_index);
  377. inst_index++;
  378. inst.opcode = INST_DATA_LASTHASH_PAD | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
  379. memset(inst.data, 0, SHA256_BLOCK_SIZE);
  380. ssp_hasher_fill_iram(&inst, inst_index);
  381. inst_index++;
  382. }
  383. /* done */
  384. inst.opcode = INST_DONE;
  385. ssp_hasher_fill_iram(&inst, inst_index);
  386. sspinfo.stratum_update = true;
  387. ssp_hasher_start();
  388. mutex_unlock(&(sspinfo.hasher_lock));
  389. }
  390. struct testcase {
  391. unsigned char *coinbase;
  392. unsigned char (*merkle_branches)[32];
  393. unsigned int coinbase_len;
  394. unsigned int merkles;
  395. unsigned int n2size;
  396. unsigned int nonce2_offset;
  397. };
  398. #define TESTCASE_COUNT 3
  399. void ssp_hasher_test(void)
  400. {
  401. struct pool test_pool[2];
  402. struct timeval t_start, t_find_pair;
  403. ssp_pair pair;
  404. uint32_t tail[2];
  405. uint32_t pair_count = 0;
  406. int i, pool_index;
  407. double pair_diff;
  408. struct testcase tc[TESTCASE_COUNT];
  409. unsigned int tci = 0;
  410. bool stratum_update = true;
  411. bool hasher_update = true;
  412. /* nonce2 4 bytes without block_nb */
  413. unsigned char coinbase[] = {
  414. 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  415. 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x64,0x03,0x85,0xc3,0x06,0x37,0xe4,0xb8,0x83,0xe5,0xbd,0xa9,0xe7,0xa5,0x9e,0xe4,0xbb,0x99,0xe9,0xb1,0xbc,0x17,0x60,
  416. 0xcb,0x03,0x29,0xf4,0xa7,0x98,0x99,0xde,0x10,0x87,0xd1,0x01,0xc6,0x1e,0x7a,0x1f,0x0f,0x25,0xc0,0xec,0xc4,0x74,0x65,0x8c,0x69,0x7c,0x78,0x79,0xa4,0x7a,0x02,0x00,
  417. 0x00,0x00,0xf0,0x9f,0x90,0x9f,0x14,0x4d,0x69,0x6e,0x65,0x64,0x20,0x62,0x79,0x20,0x71,0x69,0x6e,0x66,0x65,0x6e,0x67,0x6c,0x69,0x6e,0x67,0x00,0x00,0x00,0x00,0x00,
  418. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x5d,0xcc,0xe0,0x4b,0x00,0x00,0x00,0x00,0x19,0x76,0xa9,0x14,0xc8,
  419. 0x25,0xa1,0xec,0xf2,0xa6,0x83,0x0c,0x44,0x01,0x62,0x0c,0x3a,0x16,0xf1,0x99,0x50,0x57,0xc2,0xab,0x88,0xac,0xa0,0x60,0x82,0x2f
  420. };
  421. unsigned char merkle_branches[][32] = {
  422. {0x0d,0x44,0xd1,0xab,0xc4,0x1e,0x2f,0xed,0x72,0xa7,0x46,0xc9,0x68,0x31,0xbd,0x98,0x60,0xe5,0x32,0x6c,0x96,0xf0,0xe8,0x97,0x72,0xf4,0x59,0x0e,0x0c,0x36,0xd9,0x7c},
  423. {0x10,0x24,0x76,0x6d,0xde,0x67,0xdf,0x66,0x54,0xa8,0xac,0x19,0x8d,0x9d,0xf2,0x45,0xea,0x74,0x60,0x2d,0x0d,0xb7,0xa6,0x34,0x5e,0x2d,0x51,0xe2,0x8a,0x8e,0xb1,0xf6},
  424. {0x2c,0x03,0x81,0x54,0xf9,0xfc,0xa7,0x7d,0xc8,0x09,0xcf,0xb4,0xc2,0x12,0x11,0xbe,0xbb,0x57,0x8d,0x4f,0x80,0x1f,0x78,0xce,0x5c,0x58,0x10,0xdb,0x03,0xb8,0x33,0xaa},
  425. {0x61,0xce,0xe4,0xd0,0xb9,0x85,0xf7,0xea,0xb2,0x57,0x39,0x16,0x24,0xb1,0x3d,0xf0,0xd0,0x09,0x65,0x75,0xb2,0xf5,0x95,0x63,0x4b,0x38,0xd8,0xcf,0x8a,0x36,0xe5,0xe9},
  426. {0x09,0xb4,0x42,0x7c,0xf6,0x18,0xa4,0xe4,0x18,0xd3,0xd1,0xa1,0xe0,0x47,0x7b,0x39,0x6f,0x7c,0x1d,0x70,0x00,0xed,0x07,0xc2,0xd6,0xc1,0x03,0x5b,0x93,0xe8,0x46,0xc6},
  427. {0x71,0xb0,0x09,0x2f,0x74,0xe9,0x3a,0x86,0x85,0xc6,0x8a,0x27,0xcd,0x2b,0x80,0x13,0xf9,0x4b,0x20,0xcd,0xdb,0x8f,0xfd,0xb2,0x28,0x2e,0x17,0x4f,0xc7,0xd8,0x83,0xd5},
  428. {0x27,0xc2,0x80,0x96,0xd7,0x8f,0x41,0xfb,0x18,0x2c,0x7c,0xe8,0xce,0x59,0x5a,0x81,0x3f,0x08,0xdb,0xbb,0x02,0xd2,0x43,0x99,0x18,0x04,0x0b,0x61,0x60,0x2f,0x5f,0xba},
  429. {0xe7,0xf8,0x8a,0x99,0xf3,0x50,0x3c,0xf7,0x81,0x3b,0x9e,0x7e,0xf9,0x6c,0x98,0x85,0x4a,0x67,0x07,0x08,0x61,0x8f,0xe3,0x8c,0x3d,0x78,0xc8,0xd0,0x0e,0x14,0x86,0xf9},
  430. {0x48,0x56,0x1c,0x47,0x35,0x49,0x4b,0xdb,0x5a,0x19,0xd5,0x27,0xe5,0x7e,0x52,0x59,0x2e,0xe8,0xab,0xae,0xa1,0xc9,0x3e,0x0b,0x09,0x06,0x70,0x81,0xb8,0x38,0xa9,0x22},
  431. {0x95,0x9c,0x26,0x49,0xa2,0xcc,0xd6,0x96,0x47,0x11,0x49,0xb8,0x31,0x44,0x17,0x01,0xeb,0x32,0xac,0x95,0x07,0xf6,0xd0,0x5c,0x7c,0x0e,0xf9,0x2a,0xd3,0xc2,0xfc,0x27},
  432. };
  433. tc[0].coinbase = coinbase;
  434. tc[0].merkle_branches = merkle_branches;
  435. tc[0].coinbase_len = sizeof(coinbase);
  436. tc[0].merkles = sizeof(merkle_branches) / 32;
  437. tc[0].n2size = 4;
  438. tc[0].nonce2_offset = 142;
  439. /* nonce2 4 bytes with block_nb */
  440. unsigned char coinbase1[] = {
  441. 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  442. 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x45,0x03,0x0e,0x47,0x06,0xfa,0xbe,0x6d,0x6d,0x36,0xef,0x89,0xc9,0x76,0xd4,0xb8,0x75,0x52,0xf3,0x52,0x89,0x4a,0x26,
  443. 0xd3,0x07,0x98,0x4b,0x28,0x1d,0x6e,0x3d,0x3a,0xa2,0xa8,0xc8,0x21,0x67,0x33,0x50,0x79,0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0xad,0xbe,0xef,0xca,0xfe,
  444. 0xbe,0x00,0x00,0x00,0x00,0x10,0xe3,0x03,0x2f,0x73,0x6c,0x75,0x73,0x68,0x2f,0x00,0x00,0x00,0x00,0x01,0xeb,0xb9,0xed,0x97,0x00,0x00,0x00,0x00,0x19,0x76,0xa9,0x14,
  445. 0x7c,0x15,0x4e,0xd1,0xdc,0x59,0x60,0x9e,0x3d,0x26,0xab,0xb2,0xdf,0x2e,0xa3,0xd5,0x87,0xcd,0x8c,0x41,0x88,0xac,0x00,0x00,0x00,0x00
  446. };
  447. unsigned char merkle_branches1[][32] = {
  448. {0xf2,0xe1,0xd3,0x58,0x4d,0x02,0x24,0xfb,0x0b,0x7b,0x43,0xc8,0x87,0x41,0x3b,0xb6,0xab,0x3e,0xaf,0x5a,0x79,0x92,0x90,0xc2,0x56,0x9f,0x20,0xb5,0xfe,0x6b,0x0b,0x36},
  449. {0x36,0xb3,0xff,0xba,0x99,0xb8,0x9f,0xe4,0x0f,0xf3,0x21,0x64,0xf0,0xa1,0x19,0x86,0x0f,0x09,0x13,0x4c,0xe2,0x54,0x1e,0xff,0x38,0xc6,0xab,0x55,0xcc,0x58,0xd2,0xe4},
  450. {0x13,0xb1,0x66,0xdc,0x92,0x6f,0x3f,0x37,0xdb,0x30,0xec,0x4d,0x7b,0x37,0x38,0xac,0xf5,0x38,0xb6,0x4d,0x1f,0x11,0x6c,0xd2,0xee,0x84,0x5b,0xd2,0x15,0x62,0x99,0x78},
  451. {0x72,0x24,0xd0,0x31,0x90,0x4a,0x30,0xe0,0x7f,0x8d,0x41,0x48,0xa7,0x26,0x21,0xed,0xd3,0x47,0x0a,0xb7,0x38,0x52,0x0e,0xaf,0x65,0xab,0x3b,0xcd,0xf0,0x1c,0xeb,0x67},
  452. {0x81,0x85,0xe7,0x18,0x92,0xe5,0xf6,0xc5,0x05,0xba,0xe0,0xdb,0x45,0x45,0xfe,0x86,0x68,0x9a,0x11,0xb8,0x04,0x32,0x14,0x5c,0x72,0x1f,0xf9,0x6c,0xe5,0x26,0x86,0x0a},
  453. {0xea,0xff,0xbf,0x99,0x8f,0xfc,0x3c,0xa8,0x35,0x14,0x60,0x79,0xa3,0xdc,0x6c,0x97,0x3a,0xe7,0xb0,0xb9,0x64,0x69,0xc7,0x16,0x7b,0x17,0x12,0x46,0x87,0xdd,0x10,0x3f},
  454. {0x99,0x5a,0x04,0xf1,0x56,0xdf,0x6b,0x09,0x46,0xd2,0x65,0x23,0x6d,0x59,0xdf,0xeb,0xaa,0x60,0xda,0xd0,0x09,0xc3,0x22,0x56,0x14,0xf8,0xbd,0xd1,0x1c,0x74,0x7e,0x71},
  455. {0xf8,0x3f,0xe9,0x84,0x7c,0x0b,0x35,0x5e,0xfa,0x59,0x06,0x11,0xd2,0x82,0xd2,0x33,0x0b,0x28,0xd2,0x3d,0x18,0x4a,0x45,0x6d,0x05,0xff,0x5f,0x7b,0xaf,0x6a,0xda,0x81},
  456. {0x13,0xd7,0x5e,0xf4,0xda,0x4b,0x1a,0x2a,0xc9,0x42,0x19,0x7d,0x18,0x5e,0x93,0x4a,0xec,0x72,0x09,0xbc,0x95,0x2a,0xa2,0xdd,0xc6,0x77,0x4f,0xdb,0x1e,0x65,0x2c,0xd7},
  457. {0x85,0x6b,0x96,0xe8,0x56,0x3e,0xaa,0x9e,0x59,0x3a,0xa7,0xe0,0x29,0xc2,0xd4,0x01,0xc5,0x66,0xf7,0x8d,0x8e,0xf8,0x22,0xda,0xfe,0x79,0x5f,0x10,0x8a,0x59,0x8a,0x28},
  458. {0xce,0x79,0x63,0xa5,0x43,0xe1,0x00,0x18,0xf2,0x3e,0x3d,0xfd,0x52,0x01,0x17,0x55,0xe5,0xc8,0x47,0x37,0xa0,0xd0,0x86,0x51,0xb8,0x8c,0x89,0x56,0x71,0xf3,0x96,0x49},
  459. {0x88,0x73,0x89,0x13,0xa3,0xc7,0x3a,0xee,0x99,0x6c,0xc9,0xf5,0x76,0x0a,0xec,0x41,0xf6,0x97,0x99,0xd4,0x9b,0x09,0x36,0x4c,0x12,0xb3,0x6a,0x37,0x9c,0x18,0x42,0xef},
  460. };
  461. tc[1].coinbase = coinbase1;
  462. tc[1].merkle_branches = merkle_branches1;
  463. tc[1].coinbase_len = sizeof(coinbase1);
  464. tc[1].merkles = sizeof(merkle_branches1) / 32;
  465. tc[1].n2size = 4;
  466. tc[1].nonce2_offset = 97;
  467. /* nonce2 8 bytes */
  468. unsigned char coinbase2[] = {
  469. 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  470. 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x31,0x03,0x18,0xc4,0x06,0x00,0x04,0xa6,0xfc,0x50,0x58,0x04,0x20,0xb8,0xb4,0x15,0x0c,0x62,0xa4,0x85,0x58,0x00,0x00,
  471. 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x63,0x6b,0x70,0x6f,0x6f,0x6c,0x0d,0x2f,0x4b,0x61,0x6e,0x6f,0x20,0x2f,0x42,0x45,0x42,0x4f,0x50,0x2f,0xff,0xff,0xff,0xff,0x02,
  472. 0xe4,0xf2,0x64,0x4d,0x00,0x00,0x00,0x00,0x19,0x76,0xa9,0x14,0x1e,0xff,0xba,0x01,0xe0,0xc6,0x5d,0x69,0x44,0xe5,0x99,0x2e,0x7b,0xa5,0x3d,0x29,0xfc,0x02,0x05,0xca,
  473. 0x88,0xac,0x9b,0xef,0xb3,0x00,0x00,0x00,0x00,0x00,0x19,0x76,0xa9,0x14,0x5d,0xdd,0xa1,0xc1,0x1c,0xe7,0xdf,0x66,0x81,0xcb,0x06,0x4c,0xf9,0xaa,0xb5,0xd6,0xdf,0x44,
  474. 0xbb,0x1b,0x88,0xac,0x00,0x00,0x00,0x00
  475. };
  476. unsigned char merkle_branches2[][32] = {
  477. {0xdf,0x40,0xcf,0x4d,0x90,0x64,0xb3,0x9e,0xce,0x1a,0x32,0x42,0xb0,0x33,0x97,0xea,0x1b,0x43,0x23,0x13,0x8a,0x0a,0x51,0x52,0x7a,0x20,0x74,0xf2,0x71,0xc3,0x88,0x52},
  478. {0xed,0xb0,0x7a,0x6c,0x50,0x99,0x0f,0xe8,0x9e,0xe7,0x84,0xd7,0x82,0xa0,0xe6,0xd8,0xdd,0x99,0xd6,0x15,0x35,0x63,0xa9,0x3d,0xd3,0x6c,0xb9,0xdb,0x5a,0x1e,0x34,0x5f},
  479. {0x64,0x98,0xb5,0x26,0x04,0x8f,0x08,0x15,0xd9,0x39,0x0d,0x0f,0x32,0x08,0x57,0x49,0x83,0xcd,0x72,0x52,0x84,0xe3,0x74,0xe0,0xe5,0xda,0x5a,0xcc,0x8e,0xdb,0xe4,0x4c},
  480. {0x3c,0x78,0x9f,0x8c,0xf7,0x39,0x93,0x52,0x55,0xf4,0x34,0x42,0x9a,0x77,0xe3,0xcf,0x22,0xf6,0x1c,0x4a,0x38,0x2e,0x32,0xfd,0xb5,0xd0,0x3d,0x36,0x9b,0x31,0x79,0x5a},
  481. {0xc2,0xce,0xd4,0x9b,0x26,0xdf,0x6d,0x83,0x25,0xf8,0x33,0x94,0x60,0xf8,0x8f,0x69,0xbd,0x98,0x07,0x18,0x94,0xa4,0x5a,0x14,0x2a,0x54,0x6e,0x6d,0x88,0xb4,0xc7,0xd2},
  482. {0x4f,0x62,0x78,0x05,0xdc,0x7e,0x4d,0xc8,0x52,0x6a,0xc8,0xb2,0x86,0xf6,0x52,0x0d,0x17,0x57,0x74,0x59,0x04,0xc3,0x9d,0x38,0xa6,0xf8,0xc3,0x6b,0x74,0xfd,0x5d,0x10},
  483. {0xe1,0xd3,0xfb,0x46,0x1c,0xb4,0xbe,0xd1,0x55,0xcf,0x9e,0x21,0x2b,0x65,0xe1,0x0f,0xd1,0x65,0x1a,0x2e,0x25,0x78,0x74,0x0f,0x6c,0xb1,0x11,0xa2,0x26,0x34,0xba,0x9e},
  484. {0x63,0xd0,0x2e,0x76,0xd7,0x54,0xf7,0x67,0xef,0x9a,0x3c,0xa3,0xae,0xa0,0x5e,0xb2,0xc3,0x94,0x75,0x99,0x73,0xf0,0x40,0xa1,0x80,0x9e,0x02,0xf3,0x0e,0xed,0xcd,0x0d},
  485. {0x7f,0x51,0x79,0xc7,0x36,0x27,0xe7,0x35,0xf4,0x41,0x52,0x04,0x0a,0xd8,0x61,0xe6,0x95,0x97,0xb6,0x89,0x81,0x09,0x17,0x4e,0x09,0x2d,0x28,0xc0,0x37,0x74,0x73,0x52},
  486. {0x9c,0x37,0x53,0xe0,0x39,0x6f,0x49,0xe4,0x46,0xb9,0xf8,0x82,0x0a,0xaf,0xd0,0x7b,0x38,0xf7,0xea,0x6f,0xf8,0xc3,0x60,0x05,0x96,0x99,0x9b,0x1c,0xbb,0x51,0xd7,0x49},
  487. {0x20,0xf8,0x90,0x21,0xa8,0x4c,0xb4,0x93,0x0d,0xf8,0x1d,0xfc,0x66,0x81,0xab,0x0e,0x01,0x97,0x95,0x42,0x03,0x36,0x41,0x0f,0xfc,0x2b,0xe2,0x9a,0x31,0x34,0x8e,0x5f},
  488. };
  489. tc[2].coinbase = coinbase2;
  490. tc[2].merkle_branches = merkle_branches2;
  491. tc[2].coinbase_len = sizeof(coinbase2);
  492. tc[2].merkles = sizeof(merkle_branches2) / 32;
  493. tc[2].n2size = 8;
  494. tc[2].nonce2_offset = 62;
  495. ssp_sorter_init(HT_SIZE, HT_PRB_LMT, HT_PRB_C1, HT_PRB_C2);
  496. ssp_hasher_init();
  497. cgtime(&t_start);
  498. while (1) {
  499. if (stratum_update) {
  500. for (pool_index = 0; pool_index < 2; pool_index++) {
  501. test_pool[pool_index].coinbase_len = tc[tci].coinbase_len;
  502. test_pool[pool_index].coinbase = cgcalloc(test_pool[pool_index].coinbase_len, 1);
  503. test_pool[pool_index].merkles = tc[tci].merkles;
  504. test_pool[pool_index].swork.merkle_bin = cgmalloc(sizeof(char *) * test_pool[pool_index].merkles + 1);
  505. for (i = 0; i < test_pool[pool_index].merkles; i++) {
  506. test_pool[pool_index].swork.merkle_bin[i] = cgmalloc(32);
  507. memcpy(test_pool[pool_index].swork.merkle_bin[i], tc[tci].merkle_branches[i], 32);
  508. }
  509. memcpy(test_pool[pool_index].coinbase, tc[tci].coinbase, test_pool[pool_index].coinbase_len);
  510. test_pool[pool_index].n2size = tc[tci].n2size;
  511. test_pool[pool_index].nonce2_offset = tc[tci].nonce2_offset;
  512. }
  513. stratum_update = false;
  514. hasher_update = true;
  515. }
  516. if (ssp_sorter_get_pair(pair)) {
  517. cgtime(&t_find_pair);
  518. pair_diff = tdiff(&t_find_pair, &t_start);
  519. applog(LOG_NOTICE, "%0.8fs\tGot a pair %08x-%08x", pair_diff, pair[0], pair[1]);
  520. tail[0] = gen_merkle_root(&test_pool[1], pair[0]);
  521. tail[1] = gen_merkle_root(&test_pool[1], pair[1]);
  522. if (tail[0] != tail[1]) {
  523. applog(LOG_NOTICE, "tail mismatch (%08x:%08x -> %08x:%08x)",
  524. tail[0],
  525. tail[1],
  526. pair[0],
  527. pair[1]);
  528. } else {
  529. applog(LOG_NOTICE, "tail pass (%08x -> %08x:%08x)",
  530. tail[0],
  531. pair[0],
  532. pair[1]);
  533. }
  534. memcpy(&t_start, &t_find_pair, sizeof(t_find_pair));
  535. pair_count++;
  536. if (pair_count == 20) {
  537. stratum_update = true;
  538. pair_count = 0;
  539. tci = (tci + 1) % TESTCASE_COUNT;
  540. for (pool_index = 0; pool_index < 2; pool_index++) {
  541. free(test_pool[pool_index].coinbase);
  542. for (i = 0; i < test_pool[pool_index].merkles; i++)
  543. free(test_pool[pool_index].swork.merkle_bin[i]);
  544. }
  545. }
  546. }
  547. if (hasher_update) {
  548. hasher_update = false;
  549. ssp_hasher_update_stratum(&test_pool[0], true);
  550. }
  551. }
  552. quit(1, "ssp_hasher_test finished\n");
  553. }