Browse Source

Updated miner.c

Ricardo Iván Vieitez Parra 12 years ago
parent
commit
d754f2d5ed
1 changed files with 193 additions and 97 deletions
  1. 193 97
      miner.c

+ 193 - 97
miner.c

@@ -167,6 +167,9 @@ static bool opt_nogpu;
 #include "httpsrv.h"
 int httpsrv_port = -1;
 #endif
+#ifdef USE_LIBEVENT
+int stratumsrv_port = -1;
+#endif
 
 struct string_elist *scan_devices;
 bool opt_force_dev_init;
@@ -512,6 +515,42 @@ struct cgpu_info *get_devices(int id)
 	return cgpu;
 }
 
+static pthread_mutex_t noncelog_lock = PTHREAD_MUTEX_INITIALIZER;
+static FILE *noncelog_file = NULL;
+
+static
+void noncelog(const struct work * const work)
+{
+	const int thr_id = work->thr_id;
+	const struct cgpu_info *proc = get_thr_cgpu(thr_id);
+	char buf[0x200], hash[65], data[161], midstate[65];
+	int rv;
+	size_t ret;
+	
+	bin2hex(hash, work->hash, 32);
+	bin2hex(data, work->data, 80);
+	bin2hex(midstate, work->midstate, 32);
+	
+	// timestamp,proc,hash,data,midstate
+	rv = snprintf(buf, sizeof(buf), "%lu,%s,%s,%s,%s\n",
+	              (unsigned long)time(NULL), proc->proc_repr_ns,
+	              hash, data, midstate);
+	
+	if (unlikely(rv < 1))
+	{
+		applog(LOG_ERR, "noncelog printf error");
+		return;
+	}
+	
+	mutex_lock(&noncelog_lock);
+	ret = fwrite(buf, rv, 1, noncelog_file);
+	fflush(noncelog_file);
+	mutex_unlock(&noncelog_lock);
+	
+	if (ret != 1)
+		applog(LOG_ERR, "noncelog fwrite error");
+}
+
 static void sharelog(const char*disposition, const struct work*work)
 {
 	char target[(sizeof(work->target) * 2) + 1];
@@ -530,7 +569,7 @@ static void sharelog(const char*disposition, const struct work*work)
 	thr_id = work->thr_id;
 	cgpu = get_thr_cgpu(thr_id);
 	pool = work->pool;
-	t = (unsigned long int)(work->tv_work_found.tv_sec);
+	t = work->ts_getwork + timer_elapsed(&work->tv_getwork, &work->tv_work_found);
 	bin2hex(target, work->target, sizeof(work->target));
 	bin2hex(hash, work->hash, sizeof(work->hash));
 	bin2hex(data, work->data, sizeof(work->data));
@@ -1152,28 +1191,59 @@ char *set_log_file(char *arg)
 	return NULL;
 }
 
-static char* set_sharelog(char *arg)
+static
+char *_bfgopt_set_file(const char *arg, FILE **F, const char *mode, const char *purpose)
 {
 	char *r = "";
 	long int i = strtol(arg, &r, 10);
+	static char *err = NULL;
+	const size_t errbufsz = 0x100;
 
+	free(err);
+	err = NULL;
+	
 	if ((!*r) && i >= 0 && i <= INT_MAX) {
-		sharelog_file = fdopen((int)i, "a");
-		if (!sharelog_file)
-			applog(LOG_ERR, "Failed to open fd %u for share log", (unsigned int)i);
+		*F = fdopen((int)i, mode);
+		if (!*F)
+		{
+			err = malloc(errbufsz);
+			snprintf(err, errbufsz, "Failed to open fd %d for %s",
+			         (int)i, purpose);
+			return err;
+		}
 	} else if (!strcmp(arg, "-")) {
-		sharelog_file = stdout;
-		if (!sharelog_file)
-			applog(LOG_ERR, "Standard output missing for share log");
+		*F = (mode[0] == 'a') ? stdout : stdin;
+		if (!*F)
+		{
+			err = malloc(errbufsz);
+			snprintf(err, errbufsz, "Standard %sput missing for %s",
+			         (mode[0] == 'a') ? "out" : "in", purpose);
+			return err;
+		}
 	} else {
-		sharelog_file = fopen(arg, "a");
-		if (!sharelog_file)
-			applog(LOG_ERR, "Failed to open %s for share log", arg);
+		*F = fopen(arg, mode);
+		if (!*F)
+		{
+			err = malloc(errbufsz);
+			snprintf(err, errbufsz, "Failed to open %s for %s",
+			         arg, purpose);
+			return err;
+		}
 	}
 
 	return NULL;
 }
 
+static char *set_noncelog(char *arg)
+{
+	return _bfgopt_set_file(arg, &noncelog_file, "a", "nonce log");
+}
+
+static char *set_sharelog(char *arg)
+{
+	return _bfgopt_set_file(arg, &sharelog_file, "a", "share log");
+}
+
 static char *temp_cutoff_str = "";
 static char *temp_target_str = "";
 
@@ -1412,17 +1482,6 @@ static struct opt_table opt_config_table[] = {
 		     set_int_0_to_9999, opt_show_intval, &opt_bench_algo,
 		     opt_hidden),
 #endif
-#ifdef CHROOT
-	OPT_WITH_ARG("--chroot-dir",
-		     opt_set_charp, NULL, &chroot_dir,
-		     "Chroot to a directory right after startup"),
-	OPT_WITH_ARG("--chroot-user",
-		     opt_set_charp, NULL, &chroot_user,
-		     "Username of an unprivileged user to run as"),
-#endif
-	OPT_WITH_ARG("--cmd-idle",
-	             opt_set_charp, NULL, &cmd_idle,
-	             "Execute a command when a device is allowed to be idle (rest or wait)"),
 #ifdef CHROOT
         OPT_WITH_ARG("--chroot-dir",
                      opt_set_charp, NULL, &chroot_dir,
@@ -1431,6 +1490,9 @@ static struct opt_table opt_config_table[] = {
                      opt_set_charp, NULL, &chroot_user,
                      "Username of an unprivileged user to run as"),
 #endif
+	OPT_WITH_ARG("--cmd-idle",
+	             opt_set_charp, NULL, &cmd_idle,
+	             "Execute a command when a device is allowed to be idle (rest or wait)"),
 	OPT_WITH_ARG("--cmd-sick",
 	             opt_set_charp, NULL, &cmd_sick,
 	             "Execute a command when a device is declared sick"),
@@ -1655,6 +1717,9 @@ static struct opt_table opt_config_table[] = {
 	                opt_hidden
 #endif
 	),
+	OPT_WITH_ARG("--noncelog",
+		     set_noncelog, NULL, NULL,
+		     "Create log of all nonces found"),
 	OPT_WITH_ARG("--pass|-p",
 		     set_pass, NULL, NULL,
 		     "Password for bitcoin JSON-RPC server"),
@@ -1746,6 +1811,11 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITH_ARG("--socks-proxy",
 		     opt_set_charp, NULL, &opt_socks_proxy,
 		     "Set socks4 proxy (host:port)"),
+#ifdef USE_LIBEVENT
+	OPT_WITH_ARG("--stratum-port",
+	             opt_set_intval, opt_show_intval, &stratumsrv_port,
+	             "Port number to listen on for stratum miners (-1 means disabled)"),
+#endif
 	OPT_WITHOUT_ARG("--submit-stale",
 			opt_set_bool, &opt_submit_stale,
 	                opt_hidden),
@@ -2809,7 +2879,7 @@ void get_statline3(char *buf, size_t bufsz, struct cgpu_info *cgpu, bool for_cur
 	double wnotaccepted = cgpu->diff_rejected + cgpu->diff_stale;
 	int hwerrs = cgpu->hw_errors;
 	int badnonces = cgpu->bad_nonces;
-	int allnonces = cgpu->diff1;
+	int goodnonces = cgpu->diff1;
 	
 	if (!opt_show_procs)
 		for (struct cgpu_info *slave = cgpu; (slave = slave->next_proc); )
@@ -2827,7 +2897,7 @@ void get_statline3(char *buf, size_t bufsz, struct cgpu_info *cgpu, bool for_cur
 			wnotaccepted += slave->diff_rejected + slave->diff_stale;
 			hwerrs += slave->hw_errors;
 			badnonces += slave->bad_nonces;
-			allnonces += slave->diff1;
+			goodnonces += slave->diff1;
 		}
 	
 	multi_format_unit_array2(
@@ -2925,13 +2995,13 @@ void get_statline3(char *buf, size_t bufsz, struct cgpu_info *cgpu, bool for_cur
 		                accepted, rejected, stale,
 		                wnotaccepted, waccepted,
 		                hwerrs,
-		                badnonces, allnonces);
+		                badnonces, badnonces + goodnonces);
 	}
 	else
 #endif
 	{
 		percentf4(rejpcbuf, sizeof(rejpcbuf), wnotaccepted, waccepted);
-		percentf3(bnbuf, sizeof(bnbuf), badnonces, allnonces);
+		percentf4(bnbuf, sizeof(bnbuf), badnonces, goodnonces);
 		tailsprintf(buf, bufsz, "%ds:%s avg:%s u:%s | A:%d R:%d+%d(%s) HW:%d/%s",
 			opt_log_interval,
 			cHr, aHr, uHr,
@@ -6968,7 +7038,8 @@ static void hashmeter(int thr_id, struct timeval *diff,
 		                total_rejected,
 		                total_stale,
 		                total_diff_rejected + total_diff_stale, total_diff_accepted,
-		                hw_errors, total_bad_nonces, total_diff1);
+		                hw_errors,
+		                total_bad_nonces, total_bad_nonces + total_diff1);
 		unlock_curses();
 	}
 #endif
@@ -6978,7 +7049,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
 	uHr[5] = ' ';
 	
 	percentf4(rejpcbuf, sizeof(rejpcbuf), total_diff_rejected + total_diff_stale, total_diff_accepted);
-	percentf3(bnbuf, sizeof(bnbuf), total_bad_nonces, total_diff1);
+	percentf4(bnbuf, sizeof(bnbuf), total_bad_nonces, total_diff1);
 	
 	snprintf(logstatusline, sizeof(logstatusline),
 	         "%s%ds:%s avg:%s u:%s | A:%d R:%d+%d(%s) HW:%d/%s",
@@ -7376,14 +7447,17 @@ static void *stratum_thread(void *userdata)
 		int sel_ret;
 		fd_set rd;
 		char *s;
+		int sock;
 
 		if (unlikely(!pool->has_stratum))
 			break;
 
+		sock = pool->sock;
+		
 		/* Check to see whether we need to maintain this connection
 		 * indefinitely or just bring it up when we switch to this
 		 * pool */
-		if (!sock_full(pool) && !cnx_needed(pool)) {
+		if (sock == INVSOCK || (!sock_full(pool) && !cnx_needed(pool))) {
 			suspend_stratum(pool);
 			clear_stratum_shares(pool);
 			clear_pool_work(pool);
@@ -7400,14 +7474,14 @@ static void *stratum_thread(void *userdata)
 		}
 
 		FD_ZERO(&rd);
-		FD_SET(pool->sock, &rd);
+		FD_SET(sock, &rd);
 		timeout.tv_sec = 120;
 		timeout.tv_usec = 0;
 
 		/* If we fail to receive any notify messages for 2 minutes we
 		 * assume the connection has been dropped and treat this pool
 		 * as dead */
-		if (!sock_full(pool) && (sel_ret = select(pool->sock + 1, &rd, NULL, NULL, &timeout)) < 1) {
+		if (!sock_full(pool) && (sel_ret = select(sock + 1, &rd, NULL, NULL, &timeout)) < 1) {
 			applog(LOG_DEBUG, "Stratum select failed on pool %d with value %d", pool->pool_no, sel_ret);
 			s = NULL;
 		} else
@@ -7868,23 +7942,31 @@ void set_target(unsigned char *dest_target, double diff)
 	}
 }
 
+void stratum_work_cpy(struct stratum_work * const dst, const struct stratum_work * const src)
+{
+	*dst = *src;
+	dst->job_id = strdup(src->job_id);
+	bytes_cpy(&dst->coinbase, &src->coinbase);
+	bytes_cpy(&dst->merkle_bin, &src->merkle_bin);
+}
+
+void stratum_work_clean(struct stratum_work * const swork)
+{
+	free(swork->job_id);
+	bytes_free(&swork->coinbase);
+	bytes_free(&swork->merkle_bin);
+}
+
 /* Generates stratum based work based on the most recent notify information
  * from the pool. This will keep generating work while a pool is down so we use
  * other means to detect when the pool has died in stratum_thread */
 static void gen_stratum_work(struct pool *pool, struct work *work)
 {
-	unsigned char *coinbase, merkle_root[32], merkle_sha[64];
-	uint8_t *merkle_bin;
-	uint32_t *data32, *swap32;
-	int i;
-	
-	coinbase = bytes_buf(&pool->swork.coinbase);
-
 	clean_work(work);
-
+	
 	cg_wlock(&pool->data_lock);
-
-	/* Generate coinbase */
+	pool->swork.data_lock_p = &pool->data_lock;
+	
 	bytes_resize(&work->nonce2, pool->n2size);
 #ifndef __OPTIMIZE__
 	if (pool->nonce2sz < pool->n2size)
@@ -7898,17 +7980,35 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	       &pool->nonce2,
 #endif
 	       pool->nonce2sz);
-	memcpy(&coinbase[pool->swork.nonce2_offset], bytes_buf(&work->nonce2), pool->n2size);
 	pool->nonce2++;
+	
+	work->pool = pool;
+	work->work_restart_id = work->pool->work_restart_id;
+	gen_stratum_work2(work, &pool->swork, pool->nonce1);
+	
+	cgtime(&work->tv_staged);
+}
+
+void gen_stratum_work2(struct work *work, struct stratum_work *swork, const char *nonce1)
+{
+	unsigned char *coinbase, merkle_root[32], merkle_sha[64];
+	uint8_t *merkle_bin;
+	uint32_t *data32, *swap32;
+	int i;
+
+	/* Generate coinbase */
+	coinbase = bytes_buf(&swork->coinbase);
+	memcpy(&coinbase[swork->nonce2_offset], bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
 
-	/* Downgrade to a read lock to read off the pool variables */
-	cg_dwlock(&pool->data_lock);
+	/* Downgrade to a read lock to read off the variables */
+	if (swork->data_lock_p)
+		cg_dwlock(swork->data_lock_p);
 
 	/* Generate merkle root */
-	gen_hash(coinbase, merkle_root, bytes_len(&pool->swork.coinbase));
+	gen_hash(coinbase, merkle_root, bytes_len(&swork->coinbase));
 	memcpy(merkle_sha, merkle_root, 32);
-	merkle_bin = bytes_buf(&pool->swork.merkle_bin);
-	for (i = 0; i < pool->swork.merkles; ++i, merkle_bin += 32) {
+	merkle_bin = bytes_buf(&swork->merkle_bin);
+	for (i = 0; i < swork->merkles; ++i, merkle_bin += 32) {
 		memcpy(merkle_sha + 32, merkle_bin, 32);
 		gen_hash(merkle_sha, merkle_root, 64);
 		memcpy(merkle_sha, merkle_root, 32);
@@ -7917,21 +8017,22 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	swap32 = (uint32_t *)merkle_root;
 	flip32(swap32, data32);
 	
-	memcpy(&work->data[0], pool->swork.header1, 36);
+	memcpy(&work->data[0], swork->header1, 36);
 	memcpy(&work->data[36], merkle_root, 32);
-	*((uint32_t*)&work->data[68]) = htobe32(pool->swork.ntime + timer_elapsed(&pool->swork.tv_received, NULL));
-	memcpy(&work->data[72], pool->swork.diffbits, 4);
+	*((uint32_t*)&work->data[68]) = htobe32(swork->ntime + timer_elapsed(&swork->tv_received, NULL));
+	memcpy(&work->data[72], swork->diffbits, 4);
 	memset(&work->data[76], 0, 4);  // nonce
 	memcpy(&work->data[80], workpadding_bin, 48);
 
 	/* Store the stratum work diff to check it still matches the pool's
 	 * stratum diff when submitting shares */
-	work->sdiff = pool->swork.diff;
+	work->sdiff = swork->diff;
 
 	/* Copy parameters required for share submission */
-	work->job_id = strdup(pool->swork.job_id);
-	work->nonce1 = strdup(pool->nonce1);
-	cg_runlock(&pool->data_lock);
+	work->job_id = strdup(swork->job_id);
+	work->nonce1 = strdup(nonce1);
+	if (swork->data_lock_p)
+		cg_runlock(swork->data_lock_p);
 
 	if (opt_debug)
 	{
@@ -7948,16 +8049,12 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	set_target(work->target, work->sdiff);
 
 	local_work++;
-	work->pool = pool;
 	work->stratum = true;
 	work->blk.nonce = 0;
 	work->id = total_work++;
 	work->longpoll = false;
 	work->getwork_mode = GETWORK_MODE_STRATUM;
-	work->work_restart_id = work->pool->work_restart_id;
 	calc_diff(work, 0);
-
-	cgtime(&work->tv_staged);
 }
 
 void request_work(struct thr_info *thr)
@@ -8073,10 +8170,6 @@ void inc_hw_errors2(struct thr_info *thr, const struct work *work, const uint32_
 	++cgpu->hw_errors;
 	if (bad_nonce_p)
 	{
-		++total_diff1;
-		++cgpu->diff1;
-		if (work)
-			++work->pool->diff1;
 		++total_bad_nonces;
 		++cgpu->bad_nonces;
 	}
@@ -8156,6 +8249,9 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
 	thr->cgpu->last_device_valid_work = time(NULL);
 	mutex_unlock(&stats_lock);
 	
+	if (noncelog_file)
+		noncelog(work);
+	
 	if (res == TNR_HIGH)
 	{
 			// Share above target, normal
@@ -9799,28 +9895,41 @@ static void raise_fd_limits(void)
 #ifdef HAVE_SETRLIMIT
 	struct rlimit fdlimit;
 	unsigned long old_soft_limit;
+	char frombuf[0x10] = "unlimited";
+	char hardbuf[0x10] = "unlimited";
 	
 	if (getrlimit(RLIMIT_NOFILE, &fdlimit))
 		applogr(, LOG_DEBUG, "setrlimit: Failed to getrlimit(RLIMIT_NOFILE)");
 	
-	if (fdlimit.rlim_cur == RLIM_INFINITY)
-		applogr(, LOG_DEBUG, "setrlimit: Soft fd limit already infinite");
+	old_soft_limit = fdlimit.rlim_cur;
+	
+	if (fdlimit.rlim_max > FD_SETSIZE || fdlimit.rlim_max == RLIM_INFINITY)
+		fdlimit.rlim_cur = FD_SETSIZE;
+	else
+		fdlimit.rlim_cur = fdlimit.rlim_max;
 	
-	if (fdlimit.rlim_cur == fdlimit.rlim_max)
-		applogr(, LOG_DEBUG, "setrlimit: Soft fd limit already identical to hard limit (%lu)", (unsigned long)fdlimit.rlim_max);
+	if (fdlimit.rlim_max != RLIM_INFINITY)
+		snprintf(hardbuf, sizeof(hardbuf), "%lu", (unsigned long)fdlimit.rlim_max);
+	if (old_soft_limit != RLIM_INFINITY)
+		snprintf(frombuf, sizeof(frombuf), "%lu", old_soft_limit);
+	
+	if (fdlimit.rlim_cur == old_soft_limit)
+		applogr(, LOG_DEBUG, "setrlimit: Soft fd limit not being changed from %lu (FD_SETSIZE=%lu; hard limit=%s)",
+		        old_soft_limit, (unsigned long)FD_SETSIZE, hardbuf);
 	
-	old_soft_limit = fdlimit.rlim_cur;
-	fdlimit.rlim_cur = fdlimit.rlim_max;
 	if (setrlimit(RLIMIT_NOFILE, &fdlimit))
-		applogr(, LOG_DEBUG, "setrlimit: Failed to increase soft fd limit from %lu to hard limit of %lu", old_soft_limit, (unsigned long)fdlimit.rlim_max);
+		applogr(, LOG_DEBUG, "setrlimit: Failed to change soft fd limit from %s to %lu (FD_SETSIZE=%lu; hard limit=%s)",
+		        frombuf, (unsigned long)fdlimit.rlim_cur, (unsigned long)FD_SETSIZE, hardbuf);
 	
-	applog(LOG_DEBUG, "setrlimit: Increased soft fd limit from %lu to hard limit of %lu", old_soft_limit, (unsigned long)fdlimit.rlim_max);
+	applog(LOG_DEBUG, "setrlimit: Changed soft fd limit from %s to %lu (FD_SETSIZE=%lu; hard limit=%s)",
+	       frombuf, (unsigned long)fdlimit.rlim_cur, (unsigned long)FD_SETSIZE, hardbuf);
 #else
 	applog(LOG_DEBUG, "setrlimit: Not supported by platform");
 #endif
 }
 
 extern void bfg_init_threadlocal();
+extern void stratumsrv_start();
 
 int main(int argc, char *argv[])
 {
@@ -9978,29 +10087,6 @@ int main(int argc, char *argv[])
 #endif
 
 	raise_fd_limits();
-
-#ifdef CHROOT
-	if (chroot_dir != NULL) {
-		struct passwd *user_info = NULL;
-		if (chroot_user != NULL) {
-			if ((user_info = getpwnam(chroot_user)) == NULL) {
-				quit(1, "Unable to find user information");
-			}
-		} else if (getuid() == 0) {
-			quit(1, "Running as root is not allowed");
-		}
-
-		if (chroot(chroot_dir) == 0) {
-			if (user_info != NULL) {
-				if (setgid((*user_info).pw_gid) == 0 && setuid((*user_info).pw_uid) != 0) {
-					quit(1, "Unable to setuid");
-				}
-			}
-		} else {
-			quit(1, "Unable to chroot");
-		}
-	}
-#endif
 	
 	if (opt_benchmark) {
 		struct pool *pool;
@@ -10154,17 +10240,22 @@ int main(int argc, char *argv[])
 	}
 
 	if (!total_devices) {
-#ifndef USE_LIBMICROHTTPD
-		const int httpsrv_port = -1;
+		const bool netdev_support =
+#ifdef USE_LIBMICROHTTPD
+			(httpsrv_port != -1) ||
 #endif
-		if (httpsrv_port == -1 && (!use_curses) && !opt_api_listen)
+#ifdef USE_LIBEVENT
+			(stratumsrv_port != -1) ||
+#endif
+			false;
+		if ((!netdev_support) && (!use_curses) && !opt_api_listen)
 			quit(1, "All devices disabled, cannot mine!");
 		applog(LOG_WARNING, "No devices detected!");
 		if (use_curses)
 			applog(LOG_WARNING, "Waiting for devices; press 'M+' to add, or 'Q' to quit");
 		else
 			applog(LOG_WARNING, "Waiting for %s or press Ctrl-C to quit",
-		       (httpsrv_port == -1) ? "RPC commands" : "network devices");
+		       netdev_support ? "network devices" : "RPC commands");
 	}
 
 	load_temp_config();
@@ -10394,6 +10485,11 @@ begin_bench:
 		httpsrv_start(httpsrv_port);
 #endif
 
+#ifdef USE_LIBEVENT
+	if (stratumsrv_port != -1)
+		stratumsrv_start();
+#endif
+
 #ifdef HAVE_CURSES
 	/* Create curses input thread for keyboard input. Create this last so
 	 * that we know all threads are created since this can call kill_work