Browse Source

Refactor and simplify bin2hex to speed up and avoid unnecessary heap use

Luke Dashjr 12 years ago
parent
commit
251cfa231c
8 changed files with 73 additions and 90 deletions
  1. 10 11
      driver-bitforce.c
  2. 4 7
      driver-icarus.c
  3. 2 2
      driver-modminer.c
  4. 2 2
      driver-x6500.c
  5. 2 2
      jtag.c
  6. 37 40
      miner.c
  7. 1 1
      miner.h
  8. 15 25
      util.c

+ 10 - 11
driver-bitforce.c

@@ -131,9 +131,9 @@ void bitforce_cmd2(int fd, int procid, void *buf, size_t bufsz, const char *cmd,
 	
 	
 	if (unlikely(opt_dev_protocol))
 	if (unlikely(opt_dev_protocol))
 	{
 	{
-		char *hex = bin2hex(data, datasz);
+		char hex[(datasz * 2) + 1];
+		bin2hex(hex, data, datasz);
 		applog(LOG_DEBUG, "DEVPROTO: CMD2 (fd=%d xlink=%d): %s", fd, procid, hex);
 		applog(LOG_DEBUG, "DEVPROTO: CMD2 (fd=%d xlink=%d): %s", fd, procid, hex);
-		free(hex);
 	}
 	}
 	
 	
 	bitforce_send(fd, procid, data, datasz);
 	bitforce_send(fd, procid, data, datasz);
@@ -641,10 +641,9 @@ void dbg_block_data(struct cgpu_info *bitforce)
 		return;
 		return;
 	
 	
 	struct bitforce_data *data = bitforce->device_data;
 	struct bitforce_data *data = bitforce->device_data;
-	char *s;
-	s = bin2hex(&data->next_work_ob[8], 44);
+	char s[89];
+	bin2hex(s, &data->next_work_ob[8], 44);
 	applog(LOG_DEBUG, "%"PRIpreprv": block data: %s", bitforce->proc_repr, s);
 	applog(LOG_DEBUG, "%"PRIpreprv": block data: %s", bitforce->proc_repr, s);
-	free(s);
 }
 }
 
 
 static void bitforce_change_mode(struct cgpu_info *, enum bitforce_proto);
 static void bitforce_change_mode(struct cgpu_info *, enum bitforce_proto);
@@ -983,14 +982,14 @@ void bitforce_job_get_results(struct thr_info *thr, struct work *work)
 			{
 			{
 				// Didn't find the one we're waiting on
 				// Didn't find the one we're waiting on
 				// Must be extra stuff in the queue results
 				// Must be extra stuff in the queue results
-				char *xmid = bin2hex(work->midstate, 32);
-				char *xdt = bin2hex(&work->data[64], 12);
+				char xmid[65];
+				char xdt[25];
+				bin2hex(xmid, work->midstate, 32);
+				bin2hex(xdt, &work->data[64], 12);
 				applog(LOG_WARNING, "%"PRIpreprv": Found extra garbage in queue results: %s",
 				applog(LOG_WARNING, "%"PRIpreprv": Found extra garbage in queue results: %s",
 				       bitforce->proc_repr, pdevbuf);
 				       bitforce->proc_repr, pdevbuf);
 				applog(LOG_WARNING, "%"PRIpreprv": ...while waiting on: %s,%s",
 				applog(LOG_WARNING, "%"PRIpreprv": ...while waiting on: %s,%s",
 				       bitforce->proc_repr, xmid, xdt);
 				       bitforce->proc_repr, xmid, xdt);
-				free(xmid);
-				free(xdt);
 				count = 0;
 				count = 0;
 			}
 			}
 			else
 			else
@@ -1836,9 +1835,9 @@ void bitforce_queue_flush(struct thr_info *thr)
 			HASH_FIND(hh, processing, &key[0], sizeof(key), item);
 			HASH_FIND(hh, processing, &key[0], sizeof(key), item);
 			if (unlikely(!item))
 			if (unlikely(!item))
 			{
 			{
-				char *hex = bin2hex(key, 32+12);
+				char hex[89];
+				bin2hex(hex, key, 32+12);
 				applog(LOG_WARNING, "%"PRIpreprv": Sanity check: Device is missing queued job! %s", bitforce->proc_repr, hex);
 				applog(LOG_WARNING, "%"PRIpreprv": Sanity check: Device is missing queued job! %s", bitforce->proc_repr, hex);
-				free(hex);
 				work_list_del(&thr->work_list, work);
 				work_list_del(&thr->work_list, work);
 				continue;
 				continue;
 			}
 			}

+ 4 - 7
driver-icarus.c

@@ -547,7 +547,7 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 	const char golden_nonce[] = "000187a2";
 	const char golden_nonce[] = "000187a2";
 
 
 	unsigned char ob_bin[64], nonce_bin[ICARUS_READ_SIZE];
 	unsigned char ob_bin[64], nonce_bin[ICARUS_READ_SIZE];
-	char *nonce_hex;
+	char nonce_hex[(sizeof(nonce_bin) * 2) + 1];
 
 
 	get_options(this_option_offset, info);
 	get_options(this_option_offset, info);
 
 
@@ -572,20 +572,18 @@ bool icarus_detect_custom(const char *devpath, struct device_drv *api, struct IC
 
 
 	icarus_close(fd);
 	icarus_close(fd);
 
 
-	nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
+	bin2hex(nonce_hex, nonce_bin, sizeof(nonce_bin));
 	if (strncmp(nonce_hex, golden_nonce, 8)) {
 	if (strncmp(nonce_hex, golden_nonce, 8)) {
 		applog(LOG_DEBUG,
 		applog(LOG_DEBUG,
 			"Icarus Detect: "
 			"Icarus Detect: "
 			"Test failed at %s: get %s, should: %s",
 			"Test failed at %s: get %s, should: %s",
 			devpath, nonce_hex, golden_nonce);
 			devpath, nonce_hex, golden_nonce);
-		free(nonce_hex);
 		return false;
 		return false;
 	}
 	}
 	applog(LOG_DEBUG,
 	applog(LOG_DEBUG,
 		"Icarus Detect: "
 		"Icarus Detect: "
 		"Test succeeded at %s: got %s",
 		"Test succeeded at %s: got %s",
 			devpath, nonce_hex);
 			devpath, nonce_hex);
-	free(nonce_hex);
 
 
 	if (serial_claim_v(devpath, api))
 	if (serial_claim_v(devpath, api))
 		return false;
 		return false;
@@ -758,7 +756,6 @@ static bool icarus_start_work(struct thr_info *thr, const unsigned char *ob_bin)
 	struct icarus_state *state = thr->cgpu_data;
 	struct icarus_state *state = thr->cgpu_data;
 	int fd = icarus->device_fd;
 	int fd = icarus->device_fd;
 	int ret;
 	int ret;
-	char *ob_hex;
 
 
 	cgtime(&state->tv_workstart);
 	cgtime(&state->tv_workstart);
 
 
@@ -771,11 +768,11 @@ static bool icarus_start_work(struct thr_info *thr, const unsigned char *ob_bin)
 	}
 	}
 
 
 	if (opt_debug) {
 	if (opt_debug) {
-		ob_hex = bin2hex(ob_bin, 64);
+		char ob_hex[129];
+		bin2hex(ob_hex, ob_bin, 64);
 		applog(LOG_DEBUG, "%"PRIpreprv" sent: %s",
 		applog(LOG_DEBUG, "%"PRIpreprv" sent: %s",
 			icarus->proc_repr,
 			icarus->proc_repr,
 			ob_hex);
 			ob_hex);
-		free(ob_hex);
 	}
 	}
 
 
 	return true;
 	return true;

+ 2 - 2
driver-modminer.c

@@ -655,10 +655,10 @@ fd_set fds;
 	status_read("start work");
 	status_read("start work");
 	mutex_unlock(mutexp);
 	mutex_unlock(mutexp);
 	if (opt_debug) {
 	if (opt_debug) {
-		char *xdata = bin2hex(state->running_work.data, 80);
+		char xdata[161];
+		bin2hex(xdata, state->running_work.data, 80);
 		applog(LOG_DEBUG, "%s: Started work: %s",
 		applog(LOG_DEBUG, "%s: Started work: %s",
 		       modminer->proc_repr, xdata);
 		       modminer->proc_repr, xdata);
-		free(xdata);
 	}
 	}
 
 
 	return true;
 	return true;

+ 2 - 2
driver-x6500.c

@@ -688,10 +688,10 @@ void x6500_job_start(struct thr_info *thr)
 	mt_job_transition(thr);
 	mt_job_transition(thr);
 	
 	
 	if (opt_debug) {
 	if (opt_debug) {
-		char *xdata = bin2hex(thr->work->data, 80);
+		char xdata[161];
+		bin2hex(xdata, thr->work->data, 80);
 		applog(LOG_DEBUG, "%"PRIprepr": Started work: %s",
 		applog(LOG_DEBUG, "%"PRIprepr": Started work: %s",
 		       x6500->proc_repr, xdata);
 		       x6500->proc_repr, xdata);
-		free(xdata);
 	}
 	}
 
 
 	uint32_t usecs = 0x80000000 / fpga->dclk.freqM;
 	uint32_t usecs = 0x80000000 / fpga->dclk.freqM;

+ 2 - 2
jtag.c

@@ -83,9 +83,9 @@ bool jtag_clock(struct jtag_port *jp, bool tms, bool tdi, bool *tdo)
 	if (tdo) {
 	if (tdo) {
 		*tdo = (rbuf[rbufsz-1] & jp->tdo);
 		*tdo = (rbuf[rbufsz-1] & jp->tdo);
 #ifdef DEBUG_JTAG_CLOCK
 #ifdef DEBUG_JTAG_CLOCK
-	char *x = bin2hex(rbuf, rbufsz);
+		char x[(rbufsz * 2) + 1];
+		bin2hex(x, rbuf, rbufsz);
 	applog(LOG_DEBUG, "%p %02x tms=%d tdi=%d tdo=%d (%u:%s)", jp, (unsigned)rbuf[rbufsz-1], (int)tms, (int)tdi, (int)(bool)(rbuf[rbufsz-1] & jp->tdo), (unsigned)rbufsz, x);
 	applog(LOG_DEBUG, "%p %02x tms=%d tdi=%d tdo=%d (%u:%s)", jp, (unsigned)rbuf[rbufsz-1], (int)tms, (int)tdi, (int)(bool)(rbuf[rbufsz-1] & jp->tdo), (unsigned)rbufsz, x);
-	free(x);
 	} else {
 	} else {
 		applog(LOG_DEBUG, "%p %02x tms=%d tdi=%d tdo=?ignore", jp, (unsigned)buf[2], (int)tms, (int)tdi);
 		applog(LOG_DEBUG, "%p %02x tms=%d tdi=%d tdo=?ignore", jp, (unsigned)buf[2], (int)tms, (int)tdi);
 #endif
 #endif

+ 37 - 40
miner.c

@@ -469,7 +469,9 @@ struct cgpu_info *get_devices(int id)
 
 
 static void sharelog(const char*disposition, const struct work*work)
 static void sharelog(const char*disposition, const struct work*work)
 {
 {
-	char *target, *hash, *data;
+	char target[(sizeof(work->target) * 2) + 1];
+	char hash[(sizeof(work->hash) * 2) + 1];
+	char data[(sizeof(work->data) * 2) + 1];
 	struct cgpu_info *cgpu;
 	struct cgpu_info *cgpu;
 	unsigned long int t;
 	unsigned long int t;
 	struct pool *pool;
 	struct pool *pool;
@@ -484,15 +486,12 @@ static void sharelog(const char*disposition, const struct work*work)
 	cgpu = get_thr_cgpu(thr_id);
 	cgpu = get_thr_cgpu(thr_id);
 	pool = work->pool;
 	pool = work->pool;
 	t = (unsigned long int)(work->tv_work_found.tv_sec);
 	t = (unsigned long int)(work->tv_work_found.tv_sec);
-	target = bin2hex(work->target, sizeof(work->target));
-	hash = bin2hex(work->hash, sizeof(work->hash));
-	data = bin2hex(work->data, sizeof(work->data));
+	bin2hex(target, work->target, sizeof(work->target));
+	bin2hex(hash, work->hash, sizeof(work->hash));
+	bin2hex(data, work->data, sizeof(work->data));
 
 
 	// timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
 	// timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
 	rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->proc_repr_ns, thr_id, hash, data);
 	rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->proc_repr_ns, thr_id, hash, data);
-	free(target);
-	free(hash);
-	free(data);
 	if (rv >= (int)(sizeof(s)))
 	if (rv >= (int)(sizeof(s)))
 		s[sizeof(s) - 1] = '\0';
 		s[sizeof(s) - 1] = '\0';
 	else if (rv < 0) {
 	else if (rv < 0) {
@@ -647,7 +646,8 @@ char *set_request_diff(const char *arg, float *p)
 	
 	
 	request_bdiff = (double)*p * 0.9999847412109375;
 	request_bdiff = (double)*p * 0.9999847412109375;
 	bdiff_target_leadzero(target, request_bdiff);
 	bdiff_target_leadzero(target, request_bdiff);
-	request_target_str = bin2hex(target, 32);
+	request_target_str = malloc(65);
+	bin2hex(request_target_str, target, 32);
 	
 	
 	return NULL;
 	return NULL;
 }
 }
@@ -1945,14 +1945,13 @@ static const char *workpadding_bin = "\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
 static
 static
 void __update_block_title(const unsigned char *hash_swap)
 void __update_block_title(const unsigned char *hash_swap)
 {
 {
-	char *tmp;
 	if (hash_swap) {
 	if (hash_swap) {
+		char tmp[17];
 		// Only provided when the block has actually changed
 		// Only provided when the block has actually changed
 		free(current_hash);
 		free(current_hash);
 		current_hash = malloc(3 /* ... */ + 16 /* block hash segment */ + 1);
 		current_hash = malloc(3 /* ... */ + 16 /* block hash segment */ + 1);
-		tmp = bin2hex(&hash_swap[24], 8);
+		bin2hex(tmp, &hash_swap[24], 8);
 		sprintf(current_hash, "...%s", tmp);
 		sprintf(current_hash, "...%s", tmp);
-		free(tmp);
 		known_blkheight_current = false;
 		known_blkheight_current = false;
 	} else if (likely(known_blkheight_current)) {
 	} else if (likely(known_blkheight_current)) {
 		return;
 		return;
@@ -3127,11 +3126,13 @@ static char *submit_upstream_work_request(struct work *work)
 			req = blkmk_submit_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])));
 			req = blkmk_submit_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76])));
 		s = json_dumps(req, 0);
 		s = json_dumps(req, 0);
 		json_decref(req);
 		json_decref(req);
-		sd = bin2hex(data, 80);
+		sd = malloc(161);
+		bin2hex(sd, data, 80);
 	} else {
 	} else {
 
 
 	/* build hex string */
 	/* build hex string */
-	hexstr = bin2hex(work->data, sizeof(work->data));
+		hexstr = malloc((sizeof(work->data) * 2) + 1);
+		bin2hex(hexstr, work->data, sizeof(work->data));
 
 
 	/* build JSON-RPC request */
 	/* build JSON-RPC request */
 		s = strdup("{\"method\": \"getwork\", \"params\": [ \"");
 		s = strdup("{\"method\": \"getwork\", \"params\": [ \"");
@@ -4441,16 +4442,16 @@ next_write_sws_del:
 			struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
 			struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
 			int sshare_id;
 			int sshare_id;
 			uint32_t nonce;
 			uint32_t nonce;
-			char *nonce2hex;
-			char *noncehex;
-			char *ntimehex;
+			char nonce2hex[(bytes_len(&work->nonce2) * 2) + 1];
+			char noncehex[9];
+			char ntimehex[9];
 			
 			
 			sshare->sshare_time = time(NULL);
 			sshare->sshare_time = time(NULL);
 			sshare->work = copy_work(work);
 			sshare->work = copy_work(work);
-			nonce2hex = bin2hex(bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
+			bin2hex(nonce2hex, bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
 			nonce = *((uint32_t *)(work->data + 76));
 			nonce = *((uint32_t *)(work->data + 76));
-			noncehex = bin2hex((const unsigned char *)&nonce, 4);
-			ntimehex = bin2hex((void *)&work->data[68], 4);
+			bin2hex(noncehex, (const unsigned char *)&nonce, 4);
+			bin2hex(ntimehex, (void *)&work->data[68], 4);
 			
 			
 			mutex_lock(&sshare_lock);
 			mutex_lock(&sshare_lock);
 			/* Give the stratum share a unique id */
 			/* Give the stratum share a unique id */
@@ -4461,10 +4462,6 @@ next_write_sws_del:
 				pool->rpc_user, work->job_id, nonce2hex, ntimehex, noncehex, sshare->id);
 				pool->rpc_user, work->job_id, nonce2hex, ntimehex, noncehex, sshare->id);
 			mutex_unlock(&sshare_lock);
 			mutex_unlock(&sshare_lock);
 			
 			
-			free(nonce2hex);
-			free(noncehex);
-			free(ntimehex);
-			
 			applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->stratum_url, s);
 			applog(LOG_DEBUG, "DBG: sending %s submit RPC call: %s", pool->stratum_url, s);
 
 
 			if (likely(stratum_send(pool, s, strlen(s)))) {
 			if (likely(stratum_send(pool, s, strlen(s)))) {
@@ -4842,12 +4839,14 @@ static void restart_threads(void)
 	rd_unlock(&mining_thr_lock);
 	rd_unlock(&mining_thr_lock);
 }
 }
 
 
-static char *blkhashstr(unsigned char *hash)
+static
+void blkhashstr(char *rv, const unsigned char *hash)
 {
 {
 	unsigned char hash_swap[32];
 	unsigned char hash_swap[32];
+	
 	swap256(hash_swap, hash);
 	swap256(hash_swap, hash);
 	swap32tole(hash_swap, hash_swap, 32 / 4);
 	swap32tole(hash_swap, hash_swap, 32 / 4);
-	return bin2hex(hash_swap, 32);
+	bin2hex(rv, hash_swap, 32);
 }
 }
 
 
 static void set_curblock(char *hexstr, unsigned char *hash)
 static void set_curblock(char *hexstr, unsigned char *hash)
@@ -4863,7 +4862,8 @@ static void set_curblock(char *hexstr, unsigned char *hash)
 	cgtime(&block_timeval);
 	cgtime(&block_timeval);
 	__update_block_title(hash_swap);
 	__update_block_title(hash_swap);
 	free(current_fullhash);
 	free(current_fullhash);
-	current_fullhash = bin2hex(hash_swap, 32);
+	current_fullhash = malloc(65);
+	bin2hex(current_fullhash, hash_swap, 32);
 	get_timestamp(blocktime, &block_timeval);
 	get_timestamp(blocktime, &block_timeval);
 	cg_wunlock(&ch_lock);
 	cg_wunlock(&ch_lock);
 
 
@@ -4887,11 +4887,11 @@ static bool block_exists(char *hexstr)
 /* Tests if this work is from a block that has been seen before */
 /* Tests if this work is from a block that has been seen before */
 static inline bool from_existing_block(struct work *work)
 static inline bool from_existing_block(struct work *work)
 {
 {
-	char *hexstr = bin2hex(work->data + 8, 18);
+	char hexstr[37];
 	bool ret;
 	bool ret;
 
 
+	bin2hex(hexstr, work->data + 8, 18);
 	ret = block_exists(hexstr);
 	ret = block_exists(hexstr);
-	free(hexstr);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -4920,7 +4920,7 @@ static void set_blockdiff(const struct work *work)
 static bool test_work_current(struct work *work)
 static bool test_work_current(struct work *work)
 {
 {
 	bool ret = true;
 	bool ret = true;
-	char *hexstr;
+	char hexstr[37];
 
 
 	if (work->mandatory)
 	if (work->mandatory)
 		return ret;
 		return ret;
@@ -4928,7 +4928,7 @@ static bool test_work_current(struct work *work)
 	uint32_t block_id = ((uint32_t*)(work->data))[1];
 	uint32_t block_id = ((uint32_t*)(work->data))[1];
 
 
 	/* Hack to work around dud work sneaking into test */
 	/* Hack to work around dud work sneaking into test */
-	hexstr = bin2hex(work->data + 8, 18);
+	bin2hex(hexstr, work->data + 8, 18);
 	if (!strncmp(hexstr, "000000000000000000000000000000000000", 36))
 	if (!strncmp(hexstr, "000000000000000000000000000000000000", 36))
 		goto out_free;
 		goto out_free;
 
 
@@ -5001,8 +5001,7 @@ static bool test_work_current(struct work *work)
 					// This might detect pools trying to double-spend or 51%,
 					// This might detect pools trying to double-spend or 51%,
 					// but let's not make any accusations until it's had time
 					// but let's not make any accusations until it's had time
 					// in the real world.
 					// in the real world.
-					free(hexstr);
-					hexstr = blkhashstr(&work->data[4]);
+					blkhashstr(hexstr, &work->data[4]);
 					applog(LOG_WARNING, "%s %d is issuing work for an old block: %s",
 					applog(LOG_WARNING, "%s %d is issuing work for an old block: %s",
 					       work->longpoll ? "Longpoll from pool" : "Pool",
 					       work->longpoll ? "Longpoll from pool" : "Pool",
 					       work->pool->pool_no,
 					       work->pool->pool_no,
@@ -5026,7 +5025,6 @@ static bool test_work_current(struct work *work)
 	}
 	}
 	work->longpoll = false;
 	work->longpoll = false;
 out_free:
 out_free:
-	free(hexstr);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -7137,10 +7135,9 @@ void set_target(unsigned char *dest_target, double diff)
 	swab256(dest_target, rtarget);
 	swab256(dest_target, rtarget);
 	
 	
 	if (opt_debug) {
 	if (opt_debug) {
-		char *htarget = bin2hex(rtarget, 32);
-
+		char htarget[65];
+		bin2hex(htarget, rtarget, 32);
 		applog(LOG_DEBUG, "Generated target %s", htarget);
 		applog(LOG_DEBUG, "Generated target %s", htarget);
-		free(htarget);
 	}
 	}
 }
 }
 
 
@@ -7203,12 +7200,12 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 
 
 	if (opt_debug)
 	if (opt_debug)
 	{
 	{
-		char *header = bin2hex(work->data, 80);
-		char *nonce2hex = bin2hex(bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
+		char header[161];
+		char nonce2hex[(bytes_len(&work->nonce2) * 2) + 1];
+		bin2hex(header, work->data, 80);
+		bin2hex(nonce2hex, bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
 		applog(LOG_DEBUG, "Generated stratum header %s", header);
 		applog(LOG_DEBUG, "Generated stratum header %s", header);
 		applog(LOG_DEBUG, "Work job_id %s nonce2 %s", work->job_id, nonce2hex);
 		applog(LOG_DEBUG, "Work job_id %s nonce2 %s", work->job_id, nonce2hex);
-		free(header);
-		free(nonce2hex);
 	}
 	}
 
 
 	calc_midstate(work);
 	calc_midstate(work);

+ 1 - 1
miner.h

@@ -884,7 +884,7 @@ extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
 			     const char *rpc_req, bool, bool, int *,
 			     const char *rpc_req, bool, bool, int *,
 			     struct pool *pool, bool);
 			     struct pool *pool, bool);
 extern bool our_curl_supports_proxy_uris();
 extern bool our_curl_supports_proxy_uris();
-extern char *bin2hex(const unsigned char *p, size_t len);
+extern void bin2hex(char *out, const void *in, size_t len);
 extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
 extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
 
 
 typedef bool (*sha256_func)(struct thr_info*, const unsigned char *pmidstate,
 typedef bool (*sha256_func)(struct thr_info*, const unsigned char *pmidstate,

+ 15 - 25
util.c

@@ -668,26 +668,18 @@ char *absolute_uri(char *uri, const char *ref)
 	return abs;
 	return abs;
 }
 }
 
 
-/* Returns a malloced array string of a binary value of arbitrary length. The
- * array is rounded up to a 4 byte size to appease architectures that need
- * aligned array  sizes */
-char *bin2hex(const unsigned char *p, size_t len)
-{
-	unsigned int i;
-	ssize_t slen;
-	char *s;
-
-	slen = len * 2 + 1;
-	if (slen % 4)
-		slen += 4 - (slen % 4);
-	s = calloc(slen, 1);
-	if (unlikely(!s))
-		quit(1, "Failed to calloc in bin2hex");
+static const char _hexchars[0x10] = "0123456789abcdef";
 
 
-	for (i = 0; i < len; i++)
-		sprintf(s + (i * 2), "%02x", (unsigned int) p[i]);
-
-	return s;
+void bin2hex(char *out, const void *in, size_t len)
+{
+	const unsigned char *p = in;
+	while (len--)
+	{
+		(out++)[0] = _hexchars[p[0] >> 4];
+		(out++)[0] = _hexchars[p[0] & 0xf];
+		++p;
+	}
+	out[0] = '\0';
 }
 }
 
 
 static inline
 static inline
@@ -782,24 +774,22 @@ bool hash_target_check_v(const unsigned char *hash, const unsigned char *target)
 
 
 	if (opt_debug) {
 	if (opt_debug) {
 		unsigned char hash_swap[32], target_swap[32];
 		unsigned char hash_swap[32], target_swap[32];
-		char *hash_str, *target_str;
+		char hash_str[65];
+		char target_str[65];
 
 
 		for (int i = 0; i < 32; ++i) {
 		for (int i = 0; i < 32; ++i) {
 			hash_swap[i] = hash[31-i];
 			hash_swap[i] = hash[31-i];
 			target_swap[i] = target[31-i];
 			target_swap[i] = target[31-i];
 		}
 		}
 
 
-		hash_str = bin2hex(hash_swap, 32);
-		target_str = bin2hex(target_swap, 32);
+		bin2hex(hash_str, hash_swap, 32);
+		bin2hex(target_str, target_swap, 32);
 
 
 		applog(LOG_DEBUG, " Proof: %s\nTarget: %s\nTrgVal? %s",
 		applog(LOG_DEBUG, " Proof: %s\nTarget: %s\nTrgVal? %s",
 			hash_str,
 			hash_str,
 			target_str,
 			target_str,
 			rc ? "YES (hash <= target)" :
 			rc ? "YES (hash <= target)" :
 			     "no (false positive; hash > target)");
 			     "no (false positive; hash > target)");
-
-		free(hash_str);
-		free(target_str);
 	}
 	}
 
 
 	return rc;
 	return rc;