From 87ae66c7e6bf9f4991725cd134e8bbffad03e9b9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 13 Aug 2013 05:49:32 +1000 Subject: [PATCH] Create a work data template when receiving stratum notification, allowing a simple memcpy of the merkle root avoiding more hex2bin conversions on each work generation. --- cgminer.c | 38 ++++++++++++++------------------------ miner.h | 2 ++ util.c | 25 +++++++++++++++++++++---- 3 files changed, 37 insertions(+), 28 deletions(-) diff --git a/cgminer.c b/cgminer.c index 6cd69e95..24ed3db8 100644 --- a/cgminer.c +++ b/cgminer.c @@ -5588,7 +5588,6 @@ static void gen_stratum_work(struct pool *pool, struct work *work) { unsigned char merkle_root[32], merkle_sha[64]; uint32_t *data32, *swap32, nonce2; - char *header, *merkle_hash; size_t nonce2_len; int i; @@ -5613,20 +5612,10 @@ static void gen_stratum_work(struct pool *pool, struct work *work) data32 = (uint32_t *)merkle_sha; swap32 = (uint32_t *)merkle_root; flip32(swap32, data32); - merkle_hash = bin2hex((const unsigned char *)merkle_root, 32); - - header = calloc(pool->swork.header_len, 1); - if (unlikely(!header)) - quit(1, "Failed to calloc header in gen_stratum_work"); - snprintf(header, pool->swork.header_len, - "%s%s%s%s%s%s%s", - pool->swork.bbversion, - pool->swork.prev_hash, - merkle_hash, - pool->swork.ntime, - pool->swork.nbit, - "00000000", /* nonce */ - workpadding); + + /* Copy the data template from header_bin */ + memcpy(work->data, pool->header_bin, 128); + memcpy(work->data + pool->merkle_offset, merkle_root, 32); /* Store the stratum work diff to check it still matches the pool's * stratum diff when submitting shares */ @@ -5646,18 +5635,19 @@ static void gen_stratum_work(struct pool *pool, struct work *work) quit(1, "Failed to calloc work nonce2 in gen_stratum_work"); __bin2hex(work->nonce2, (const unsigned char *)&nonce2, sizeof(uint32_t)); - applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash); - applog(LOG_DEBUG, "Generated stratum header %s", header); - applog(LOG_DEBUG, "Work job_id %s nonce2 %s ntime %s", work->job_id, work->nonce2, work->ntime); + if (opt_debug) { + char *header, *merkle_hash; - free(merkle_hash); + header = bin2hex(work->data, 128); + merkle_hash = bin2hex((const unsigned char *)merkle_root, 32); + applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash); + applog(LOG_DEBUG, "Generated stratum header %s", header); + applog(LOG_DEBUG, "Work job_id %s nonce2 %s ntime %s", work->job_id, work->nonce2, work->ntime); + free(header); + free(merkle_hash); + } - /* Convert hex data to binary data for work */ - if (unlikely(!hex2bin(work->data, header, 128))) - quit(1, "Failed to convert header to data in gen_stratum_work"); - free(header); calc_midstate(work); - set_target(work->target, work->sdiff); local_work++; diff --git a/miner.h b/miner.h index 68f6290f..ad10ddb9 100644 --- a/miner.h +++ b/miner.h @@ -1212,6 +1212,8 @@ struct pool { /* Shared by both stratum & GBT */ unsigned char *coinbase; int nonce2_offset; + unsigned char header_bin[128]; + int merkle_offset; struct timeval tv_lastwork; }; diff --git a/util.c b/util.c index f42515b0..e7a64704 100644 --- a/util.c +++ b/util.c @@ -1203,9 +1203,12 @@ static char *json_array_string(json_t *val, unsigned int entry) return NULL; } +static char *blank_merkel = "0000000000000000000000000000000000000000000000000000000000000000"; + static bool parse_notify(struct pool *pool, json_t *val) { - char *job_id, *prev_hash, *coinbase1, *coinbase2, *bbversion, *nbit, *ntime; + char *job_id, *prev_hash, *coinbase1, *coinbase2, *bbversion, *nbit, + *ntime, *header; size_t cb1_len, cb2_len, alloc_len; unsigned char *cb1, *cb2; bool clean, ret = false; @@ -1281,15 +1284,29 @@ static bool parse_notify(struct pool *pool, json_t *val) pool->swork.merkles = merkles; if (clean) pool->nonce2 = 0; - pool->swork.header_len = strlen(pool->swork.bbversion) + - strlen(pool->swork.prev_hash) + + pool->merkle_offset = strlen(pool->swork.bbversion) + + strlen(pool->swork.prev_hash); + pool->swork.header_len = pool->merkle_offset + + /* merkle_hash */ 32 + strlen(pool->swork.ntime) + strlen(pool->swork.nbit) + - /* merkle_hash */ 32 + /* nonce */ 8 + /* workpadding */ 96; + pool->merkle_offset /= 2; pool->swork.header_len = pool->swork.header_len * 2 + 1; align_len(&pool->swork.header_len); + header = alloca(pool->swork.header_len); + snprintf(header, pool->swork.header_len, + "%s%s%s%s%s%s%s", + pool->swork.bbversion, + pool->swork.prev_hash, + blank_merkel, + pool->swork.ntime, + pool->swork.nbit, + "00000000", /* nonce */ + workpadding); + if (unlikely(!hex2bin(pool->header_bin, header, 128))) + quit(1, "Failed to convert header to header_bin in parse_notify"); cb1 = calloc(cb1_len, 1); if (unlikely(!cb1))