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.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
diff --git a/cgminer.c b/cgminer.c
index 6cd69e9..24ed3db 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 68f6290..ad10ddb 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 f42515b..e7a6470 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))