Commit 87ae66c7e6bf9f4991725cd134e8bbffad03e9b9

Con Kolivas 2013-08-13T05:49:32

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.

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))