123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- /*
- * Copyright 2016 Mikeqin <Fengling.Qin@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at your option)
- * any later version. See COPYING for more details.
- */
- #include <stdbool.h>
- #include <stdint.h>
- #include <string.h>
- #include <pthread.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include "sha2.h"
- #include "libssplus.h"
- #define INSTRUCTIONS_RAM_START 0x42000000
- #define INSTRUCTIONS_RAM_SIZE (1 << 16)
- #define POINTS_RAM_START 0xfffc0000
- #define POINTS_RAM_SIZE (256 << 10)
- /* hasher instructions */
- #define INST_DONE 0x00040000
- #define INST_DATA_IRAM 0x0
- #define INST_DATA_LASTHASH_PAD 0x14000000
- #define INST_DATA_LASTHASH_IRAM 0x10000000
- #define INST_DATA_PAD512 0x26000000
- #define INST_MID_INIT 0x0
- #define INST_MID_LASTHASH 0x100000
- #define NEXT_ADDR(x) (((x) & 0x1ff) << 8)
- #define UNPACK32(x, str) \
- { \
- *((str) + 3) = (uint8_t) ((x) ); \
- *((str) + 2) = (uint8_t) ((x) >> 8); \
- *((str) + 1) = (uint8_t) ((x) >> 16); \
- *((str) + 0) = (uint8_t) ((x) >> 24); \
- }
- #define SORTER_DEBUG
- struct ssp_hasher_instruction {
- uint32_t opcode;
- uint8_t data[64];
- };
- struct ssp_point {
- uint32_t nonce2;
- uint32_t tail;
- };
- struct ssp_info {
- pthread_t hasher_thr;
- pthread_mutex_t hasher_lock;
- volatile uint32_t *iram_addr;
- volatile uint64_t *pram_addr;
- bool stratum_update;
- bool run;
- };
- struct ssp_pair_element {
- uint32_t nonce2[2];
- struct ssp_pair_element *next;
- };
- struct ssp_hashtable {
- struct ssp_point *cells;
- uint32_t size;
- uint32_t max_size; /* must be powers of 2 */
- uint32_t limit; /* probing limit */
- uint32_t c1;
- uint32_t c2;
- };
- static struct ssp_info sspinfo;
- static struct ssp_hashtable *ssp_ht = NULL;
- static struct ssp_pair_element *ssp_pair_head = NULL;
- static struct ssp_pair_element *ssp_pair_tail = NULL;
- #ifdef SORTER_DEBUG
- static uint32_t pair_count = 0;
- static uint32_t consumed = 0;
- static uint32_t discarded = 0;
- static uint32_t calls = 0;
- static struct timeval ssp_ti, ssp_tf;
- static double insert_time = .0;
- static uint32_t maxnonce = 0;
- static uint32_t ver = 0;
- #endif
- static void ssp_sorter_insert(const struct ssp_point *point)
- {
- uint32_t i;
- uint32_t key;
- #ifdef SORTER_DEBUG
- if (calls == 0xffffffff)
- applog(LOG_NOTICE, "calls overflow");
- calls++;
- #endif
- for (i = 0; i < ssp_ht->limit; i++) {
- key = (point->tail + ssp_ht->c1 * i + ssp_ht->c2 * i * i) %
- (ssp_ht->max_size);
- if (ssp_ht->cells[key].nonce2 == 0 && ssp_ht->cells[key].tail == 0) {
- /* insert */
- ssp_ht->cells[key].tail = point->tail;
- ssp_ht->cells[key].nonce2 = point->nonce2;
- ssp_ht->size++;
- goto out;
- }
- if (ssp_ht->cells[key].tail == point->tail) {
- /* get a collision */
- ssp_pair_tail->nonce2[0] = point->nonce2;
- ssp_pair_tail->nonce2[1] = ssp_ht->cells[key].nonce2;
- ssp_pair_tail->next = (struct ssp_pair_element *)cgmalloc(sizeof(struct ssp_pair_element));
- ssp_pair_tail = ssp_pair_tail->next;
- #ifdef SORTER_DEBUG
- pair_count++;
- #endif
- /* update nonce2 of the point */
- ssp_ht->cells[key].nonce2 = 0;
- ssp_ht->cells[key].tail = 0;
- /* or just delete it? */
- /* or leave it be? */
- goto out;
- }
- }
- /* discard */
- #ifdef SORTER_DEBUG
- discarded++;
- #endif
- out:
- return;
- }
- void ssp_sorter_init(uint32_t max_size, uint32_t limit, uint32_t c1, uint32_t c2)
- {
- #ifdef SORTER_DEBUG
- cgtime(&ssp_ti);
- #endif
- ssp_ht = (struct ssp_hashtable *)cgmalloc(sizeof(struct ssp_hashtable));
- ssp_ht->max_size = max_size;
- ssp_ht->limit = limit;
- ssp_ht->c1 = c1;
- ssp_ht->c2 = c2;
- ssp_ht->size = 0;
- ssp_ht->cells = (struct ssp_point *)cgmalloc(sizeof(struct ssp_point) * max_size);
- memset(ssp_ht->cells, 0, sizeof(struct ssp_point) * max_size);
- ssp_pair_head = (struct ssp_pair_element *)cgmalloc(sizeof(struct ssp_pair_element));
- ssp_pair_tail = ssp_pair_head;
- }
- void ssp_sorter_flush(void)
- {
- #ifdef SORTER_DEBUG
- double delta_t;
- cgtime(&ssp_tf);
- delta_t = tdiff(&ssp_tf, &ssp_ti);
- applog(LOG_NOTICE, "Stratum %d: %f s", ver, delta_t);
- applog(LOG_NOTICE, "Stratum %d: get %d pairs. %f pair/s", ver, pair_count, pair_count / delta_t);
- applog(LOG_NOTICE, "Stratum %d: consume %d pairs. %f pair/s", ver, consumed, consumed / delta_t);
- applog(LOG_NOTICE, "Stratum %d: discard %d points. %f point/s", ver, discarded, discarded / delta_t);
- 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);
- 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);
- applog(LOG_NOTICE, "Stratum %d: %d calls of sorter_insert. %f call/s", ver, calls, calls / delta_t);
- applog(LOG_NOTICE, "Stratum %d: avg call time - %f us", ver, delta_t * 1000000 / calls);
- applog(LOG_NOTICE, "Stratum %d: k^2 / 2N / pair - %f", ver, 0.5 * calls * calls / 4294967296 / pair_count);
- applog(LOG_NOTICE, "========================================================");
- cgtime(&ssp_ti);
- pair_count = 0;
- consumed = 0;
- discarded = 0;
- calls = 0;
- insert_time = 0;
- ver++;
- #endif
- ssp_ht->size = 0;
- memset(ssp_ht->cells, 0, sizeof(struct ssp_point) * ssp_ht->max_size);
- /* MM only use one stratum, we need drop all pairs */
- while (ssp_pair_head != ssp_pair_tail) {
- struct ssp_pair_element *tmp;
- tmp = ssp_pair_head;
- ssp_pair_head = tmp->next;
- free(tmp);
- }
- }
- int ssp_sorter_get_pair(ssp_pair pair)
- {
- struct ssp_pair_element *tmp;
- mutex_lock(&(sspinfo.hasher_lock));
- if (ssp_pair_head == ssp_pair_tail) {
- mutex_unlock(&(sspinfo.hasher_lock));
- return 0;
- }
- tmp = ssp_pair_head;
- pair[0] = tmp->nonce2[0];
- pair[1] = tmp->nonce2[1];
- ssp_pair_head = tmp->next;
- free(tmp);
- #ifdef SORTER_DEBUG
- consumed++;
- #endif
- mutex_unlock(&(sspinfo.hasher_lock));
- return 1;
- }
- static void *ssp_hasher_thread(void *userdata)
- {
- uint32_t last_nonce2 = 0, point_index = 0, nonce2;
- bool valid_nonce2 = false;
- struct ssp_info *p_ssp_info = (struct ssp_info *)userdata;
- while (1) {
- mutex_lock(&(sspinfo.hasher_lock));
- if (!p_ssp_info->run)
- valid_nonce2 = false;
- if (p_ssp_info->stratum_update) {
- p_ssp_info->stratum_update = false;
- point_index = 0;
- last_nonce2 = 0;
- valid_nonce2 = false;
- ssp_sorter_flush();
- applog(LOG_NOTICE, "libssplus: stratum update");
- }
- /* Note: hasher is fast enough, so the new job will start with a lower nonce2 */
- nonce2 = (sspinfo.pram_addr[point_index] & 0xffffffff);
- if (last_nonce2 > nonce2)
- valid_nonce2 = true;
- point_index = (point_index + 1) % (POINTS_RAM_SIZE / sizeof(struct ssp_point));
- if (valid_nonce2) {
- #ifdef SORTER_DEBUG
- if (nonce2 > maxnonce)
- maxnonce = nonce2;
- #endif
- ssp_sorter_insert((struct ssp_point *)&sspinfo.pram_addr[point_index]);
- }
- last_nonce2 = nonce2;
- mutex_unlock(&(sspinfo.hasher_lock));
- }
- return NULL;
- }
- static inline void ssp_hasher_fill_iram(struct ssp_hasher_instruction *p_inst, uint32_t inst_index)
- {
- uint8_t i;
- volatile uint32_t *p_iram_addr;
- uint32_t tmp;
- p_iram_addr = sspinfo.iram_addr + inst_index * 32;
- p_iram_addr[0] = p_inst->opcode;
- simplelog(LOG_DEBUG, "iram[%d*32+0] = 0x%08x;", inst_index, p_inst->opcode);
- for (i = 0; i < 16; i++) {
- tmp = ((p_inst->data[i * 4 + 0] << 24) |
- (p_inst->data[i * 4 + 1] << 16) |
- (p_inst->data[i * 4 + 2] << 8) |
- (p_inst->data[i * 4 + 3]));
- p_iram_addr[i + 1] = tmp;
- simplelog(LOG_DEBUG, "iram[%d*32+%d] = 0x%08x;", inst_index, i + 1, tmp);
- }
- p_iram_addr[i + 1] = 0x1; /* flush */
- simplelog(LOG_DEBUG, "iram[%d*32+%d] = 1;", inst_index, i + 1);
- }
- static inline void ssp_hasher_stop(void)
- {
- sspinfo.iram_addr[31] = 1;
- sspinfo.run = false;
- }
- static inline void ssp_hasher_start(void)
- {
- sspinfo.iram_addr[31] = 0;
- sspinfo.run = true;
- }
- int ssp_hasher_init(void)
- {
- int memfd;
- memfd = open("/dev/mem", O_RDWR | O_SYNC);
- if (memfd < 0) {
- applog(LOG_ERR, "libssplus: failed open /dev/mem");
- return 1;
- }
- sspinfo.iram_addr = (volatile uint32_t *)mmap(NULL, INSTRUCTIONS_RAM_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, memfd,
- INSTRUCTIONS_RAM_START);
- if (sspinfo.iram_addr == MAP_FAILED) {
- close(memfd);
- applog(LOG_ERR, "libssplus: mmap instructions ram failed");
- return 1;
- }
- sspinfo.pram_addr = (volatile uint64_t *)mmap(NULL, POINTS_RAM_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_SHARED, memfd,
- POINTS_RAM_START);
- if (sspinfo.pram_addr == MAP_FAILED) {
- close(memfd);
- applog(LOG_ERR, "libssplus: mmap points ram failed");
- return 1;
- }
- close(memfd);
- if (pthread_create(&(sspinfo.hasher_thr), NULL, ssp_hasher_thread, &sspinfo)) {
- applog(LOG_ERR, "libssplus: create thread failed");
- return 1;
- }
- sspinfo.stratum_update = false;
- ssp_hasher_stop();
- mutex_init(&sspinfo.hasher_lock);
- return 0;
- }
- static inline void sha256_prehash(const unsigned char *message, unsigned int len, unsigned char *digest)
- {
- int i;
- sha256_ctx ctx;
- sha256_init(&ctx);
- sha256_update(&ctx, message, len);
- for (i = 0; i < 8; i++)
- UNPACK32(ctx.h[i], &digest[i << 2]);
- }
- void ssp_hasher_update_stratum(struct pool *pool, bool clean)
- {
- struct ssp_hasher_instruction inst;
- uint32_t coinbase_len_posthash, coinbase_len_prehash;
- uint32_t i, len_rem, block_nb;
- int merkle_index;
- uint32_t inst_index = 0, nonce2_init = 0;
- uint64_t coinbase_len_bits = pool->coinbase_len * 8;
- mutex_lock(&(sspinfo.hasher_lock));
- ssp_hasher_stop();
- /* instruction init */
- inst.opcode = 0;
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- inst.data[28] = (nonce2_init >> 24) & 0xff;
- inst.data[29] = (nonce2_init >> 16) & 0xff;
- inst.data[30] = (nonce2_init >> 8) & 0xff;
- inst.data[31] = (nonce2_init) & 0xff;
- coinbase_len_prehash = pool->nonce2_offset - (pool->nonce2_offset % SHA256_BLOCK_SIZE);
- sha256_prehash(pool->coinbase, coinbase_len_prehash, inst.data + 32);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- /* coinbase */
- coinbase_len_posthash = pool->coinbase_len - coinbase_len_prehash;
- block_nb = coinbase_len_posthash / SHA256_BLOCK_SIZE;
- len_rem = (coinbase_len_posthash % SHA256_BLOCK_SIZE);
- for (i = 0; i < block_nb; i++) {
- inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
- if (!i) {
- inst.opcode |= (63 - (pool->nonce2_offset % SHA256_BLOCK_SIZE));
- inst.opcode |= INST_MID_INIT;
- } else
- inst.opcode |= INST_MID_LASTHASH;
- memcpy(inst.data, pool->coinbase + coinbase_len_prehash + i * SHA256_BLOCK_SIZE, SHA256_BLOCK_SIZE);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- }
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
- if (!block_nb) {
- inst.opcode |= (63 - (pool->nonce2_offset % SHA256_BLOCK_SIZE));
- inst.opcode |= INST_MID_INIT;
- } else
- inst.opcode |= INST_MID_LASTHASH;
- memcpy(inst.data, pool->coinbase + coinbase_len_prehash + (block_nb * SHA256_BLOCK_SIZE), len_rem);
- inst.data[len_rem] = 0x80;
- if (len_rem <= (SHA256_BLOCK_SIZE - 9)) {
- for (i = 0; i < 8; i++)
- inst.data[63 - i] = (coinbase_len_bits >> (i * 8)) & 0xff;
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- } else {
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- inst.opcode = INST_DATA_IRAM | NEXT_ADDR(inst_index + 1);
- inst.opcode |= INST_MID_LASTHASH;
- for (i = 0; i < 8; i++)
- inst.data[63 - i] = (coinbase_len_bits >> (i * 8)) & 0xff;
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- }
- /* double hash coinbase */
- inst.opcode = INST_DATA_LASTHASH_PAD | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- /* merkle branches */
- for (merkle_index = 0; merkle_index < pool->merkles; merkle_index++) {
- inst.opcode = INST_DATA_LASTHASH_IRAM | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
- memcpy(inst.data + 32, pool->swork.merkle_bin[merkle_index], 32);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- inst.opcode = INST_DATA_PAD512 | INST_MID_LASTHASH | NEXT_ADDR(inst_index + 1);
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- inst.opcode = INST_DATA_LASTHASH_PAD | INST_MID_INIT | NEXT_ADDR(inst_index + 1);
- memset(inst.data, 0, SHA256_BLOCK_SIZE);
- ssp_hasher_fill_iram(&inst, inst_index);
- inst_index++;
- }
- /* done */
- inst.opcode = INST_DONE;
- ssp_hasher_fill_iram(&inst, inst_index);
- sspinfo.stratum_update = true;
- ssp_hasher_start();
- mutex_unlock(&(sspinfo.hasher_lock));
- }
- struct testcase {
- unsigned char *coinbase;
- unsigned char (*merkle_branches)[32];
- unsigned int coinbase_len;
- unsigned int merkles;
- unsigned int n2size;
- unsigned int nonce2_offset;
- };
- #define TESTCASE_COUNT 3
- void ssp_hasher_test(void)
- {
- struct pool test_pool[2];
- struct timeval t_start, t_find_pair;
- ssp_pair pair;
- uint32_t tail[2];
- uint32_t pair_count = 0;
- int i, pool_index;
- double pair_diff;
- struct testcase tc[TESTCASE_COUNT];
- unsigned int tci = 0;
- bool stratum_update = true;
- bool hasher_update = true;
- /* nonce2 4 bytes without block_nb */
- unsigned char coinbase[] = {
- 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,
- 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,
- 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,
- 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,
- 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,
- 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
- };
- unsigned char merkle_branches[][32] = {
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- };
- tc[0].coinbase = coinbase;
- tc[0].merkle_branches = merkle_branches;
- tc[0].coinbase_len = sizeof(coinbase);
- tc[0].merkles = sizeof(merkle_branches) / 32;
- tc[0].n2size = 4;
- tc[0].nonce2_offset = 142;
- /* nonce2 4 bytes with block_nb */
- unsigned char coinbase1[] = {
- 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,
- 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,
- 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,
- 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,
- 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
- };
- unsigned char merkle_branches1[][32] = {
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- };
- tc[1].coinbase = coinbase1;
- tc[1].merkle_branches = merkle_branches1;
- tc[1].coinbase_len = sizeof(coinbase1);
- tc[1].merkles = sizeof(merkle_branches1) / 32;
- tc[1].n2size = 4;
- tc[1].nonce2_offset = 97;
- /* nonce2 8 bytes */
- unsigned char coinbase2[] = {
- 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,
- 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,
- 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,
- 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,
- 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,
- 0xbb,0x1b,0x88,0xac,0x00,0x00,0x00,0x00
- };
- unsigned char merkle_branches2[][32] = {
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- {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},
- };
- tc[2].coinbase = coinbase2;
- tc[2].merkle_branches = merkle_branches2;
- tc[2].coinbase_len = sizeof(coinbase2);
- tc[2].merkles = sizeof(merkle_branches2) / 32;
- tc[2].n2size = 8;
- tc[2].nonce2_offset = 62;
- ssp_sorter_init(HT_SIZE, HT_PRB_LMT, HT_PRB_C1, HT_PRB_C2);
- ssp_hasher_init();
- cgtime(&t_start);
- while (1) {
- if (stratum_update) {
- for (pool_index = 0; pool_index < 2; pool_index++) {
- test_pool[pool_index].coinbase_len = tc[tci].coinbase_len;
- test_pool[pool_index].coinbase = cgcalloc(test_pool[pool_index].coinbase_len, 1);
- test_pool[pool_index].merkles = tc[tci].merkles;
- test_pool[pool_index].swork.merkle_bin = cgmalloc(sizeof(char *) * test_pool[pool_index].merkles + 1);
- for (i = 0; i < test_pool[pool_index].merkles; i++) {
- test_pool[pool_index].swork.merkle_bin[i] = cgmalloc(32);
- memcpy(test_pool[pool_index].swork.merkle_bin[i], tc[tci].merkle_branches[i], 32);
- }
- memcpy(test_pool[pool_index].coinbase, tc[tci].coinbase, test_pool[pool_index].coinbase_len);
- test_pool[pool_index].n2size = tc[tci].n2size;
- test_pool[pool_index].nonce2_offset = tc[tci].nonce2_offset;
- }
- stratum_update = false;
- hasher_update = true;
- }
- if (ssp_sorter_get_pair(pair)) {
- cgtime(&t_find_pair);
- pair_diff = tdiff(&t_find_pair, &t_start);
- applog(LOG_NOTICE, "%0.8fs\tGot a pair %08x-%08x", pair_diff, pair[0], pair[1]);
- tail[0] = gen_merkle_root(&test_pool[1], pair[0]);
- tail[1] = gen_merkle_root(&test_pool[1], pair[1]);
- if (tail[0] != tail[1]) {
- applog(LOG_NOTICE, "tail mismatch (%08x:%08x -> %08x:%08x)",
- tail[0],
- tail[1],
- pair[0],
- pair[1]);
- } else {
- applog(LOG_NOTICE, "tail pass (%08x -> %08x:%08x)",
- tail[0],
- pair[0],
- pair[1]);
- }
- memcpy(&t_start, &t_find_pair, sizeof(t_find_pair));
- pair_count++;
- if (pair_count == 20) {
- stratum_update = true;
- pair_count = 0;
- tci = (tci + 1) % TESTCASE_COUNT;
- for (pool_index = 0; pool_index < 2; pool_index++) {
- free(test_pool[pool_index].coinbase);
- for (i = 0; i < test_pool[pool_index].merkles; i++)
- free(test_pool[pool_index].swork.merkle_bin[i]);
- }
- }
- }
- if (hasher_update) {
- hasher_update = false;
- ssp_hasher_update_stratum(&test_pool[0], true);
- }
- }
- quit(1, "ssp_hasher_test finished\n");
- }
|