Commit 4128b954a6e73c67b0b9d01ee3e480cd7aaefa38

Con Kolivas 2011-09-26T18:49:15

Add a --donation feature which reads a url/userpass from the author's site and contributes a percentage of getworks to the author, but default to off.

diff --git a/main.c b/main.c
index e5fefb7..1596949 100644
--- a/main.c
+++ b/main.c
@@ -265,6 +265,10 @@ static unsigned int total_go, total_ro;
 
 static struct pool *pools[MAX_POOLS];
 static struct pool *currentpool = NULL;
+
+static float opt_donation = 0.0;
+static struct pool donationpool;
+
 static int total_pools;
 static enum pool_strategy pool_strategy = POOL_FAILOVER;
 static int opt_rotate_period;
@@ -961,6 +965,18 @@ static char *set_int_1_to_10(const char *arg, int *i)
 	return set_int_range(arg, i, 1, 10);
 }
 
+static char *set_float_0_to_99(const char *arg, float *f)
+{
+	char *err = opt_set_floatval(arg, f);
+	if (err)
+		return err;
+
+	if (*f < 0.0 || *f > 99.9)
+		return "Value out of range";
+
+	return NULL;
+}
+
 static char *set_devices(const char *arg, int *i)
 {
 	char *err = opt_set_intval(arg, i);
@@ -1458,6 +1474,11 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--disable-gpu|-G",
 			opt_set_bool, &opt_nogpu,
 			"Disable GPU mining even if suitable devices exist"),
+#endif
+	OPT_WITH_ARG("--donation",
+		     set_float_0_to_99, &opt_show_floatval, &opt_donation,
+		     "Set donation percentage to cgminer author (0.0 - 99.9)"),
+#ifdef HAVE_OPENCL
 	OPT_WITHOUT_ARG("--enable-cpu|-C",
 			opt_set_bool, &opt_usecpu,
 			"Enable CPU mining with GPU mining (default: no CPU mining if suitable GPUs exist)"),
@@ -2085,6 +2106,11 @@ bool regeneratehash(const struct work *work)
 		return false;
 }
 
+static bool donor(struct pool *pool)
+{
+	return (pool == &donationpool);
+}
+
 static bool submit_upstream_work(const struct work *work)
 {
 	char *hexstr = NULL;
@@ -2130,11 +2156,14 @@ static bool submit_upstream_work(const struct work *work)
 		if (!pool_tset(pool, &pool->submit_fail)) {
 			total_ro++;
 			pool->remotefail_occasions++;
-			applog(LOG_WARNING, "Pool %d communication failure, caching submissions", pool->pool_no);
+			if (!donor(pool))
+				applog(LOG_WARNING, "Pool %d communication failure, caching submissions", pool->pool_no);
 		}
 		goto out;
-	} else if (pool_tclear(pool, &pool->submit_fail))
-		applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no);
+	} else if (pool_tclear(pool, &pool->submit_fail)) {
+		if (!donor(pool))
+			applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no);
+	}
 
 	res = json_object_get(val, "result");
 
@@ -2156,7 +2185,10 @@ static bool submit_upstream_work(const struct work *work)
 		if (opt_debug)
 			applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
 		if (!QUIET) {
-			if (total_pools > 1)
+			if (donor(work->pool))
+				applog(LOG_NOTICE, "Accepted %s %sPU %d thread %d donate",
+				       hashshow, cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, thr_id);
+			else if (total_pools > 1)
 				applog(LOG_NOTICE, "Accepted %s %sPU %d thread %d pool %d",
 				       hashshow, cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, thr_id, work->pool->pool_no);
 			else
@@ -2175,7 +2207,10 @@ static bool submit_upstream_work(const struct work *work)
 		if (opt_debug)
 			applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)");
 		if (!QUIET) {
-			if (total_pools > 1)
+			if (donor(work->pool))
+				applog(LOG_NOTICE, "Rejected %s %sPU %d thread %d donate",
+				       hashshow, cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, thr_id);
+			else if (total_pools > 1)
 				applog(LOG_NOTICE, "Rejected %s %sPU %d thread %d pool %d",
 				       hashshow, cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, thr_id, work->pool->pool_no);
 			else
@@ -2214,6 +2249,10 @@ static inline struct pool *select_pool(bool lagging)
 	static int rotating_pool = 0;
 	struct pool *pool, *cp;
 
+	if (total_getworks && opt_donation > 0.0 && !donationpool.idle &&
+	   (float)donationpool.getwork_requested / (float)total_getworks < opt_donation / 100)
+		return &donationpool;
+
 	cp = current_pool();
 
 	if (pool_strategy != POOL_LOADBALANCE && !lagging)
@@ -3601,7 +3640,8 @@ static bool pool_active(struct pool *pool, bool pinging)
 static void pool_died(struct pool *pool)
 {
 	if (!pool_tset(pool, &pool->idle)) {
-		applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
+		if (!donor(pool))
+			applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
 		gettimeofday(&pool->tv_idle, NULL);
 		switch_pools(NULL);
 	}
@@ -3619,7 +3659,8 @@ static inline int cp_prio(void)
 
 static void pool_resus(struct pool *pool)
 {
-	applog(LOG_WARNING, "Pool %d %s recovered", pool->pool_no, pool->rpc_url);
+	if (!donor(pool))
+		applog(LOG_WARNING, "Pool %d %s recovered", pool->pool_no, pool->rpc_url);
 	if (pool->prio < cp_prio() && pool_strategy == POOL_FAILOVER)
 		switch_pools(NULL);
 }
@@ -3708,7 +3749,7 @@ static inline bool should_roll(struct work *work)
 static inline bool can_roll(struct work *work)
 {
 	return (work->pool && !stale_work(work) && work->rolltime &&
-		work->rolls < 11 && !work->clone);
+		work->rolls < 11 && !work->clone && !donor(work->pool));
 }
 
 static void roll_work(struct work *work)
@@ -4791,6 +4832,14 @@ static void *watchdog_thread(void *userdata)
 			}
 		}
 
+		if (opt_donation > 0.0) {
+			if (donationpool.idle && now.tv_sec - donationpool.tv_idle.tv_sec > 60) {
+				gettimeofday(&donationpool.tv_idle, NULL);
+				if (pool_active(&donationpool, true) && pool_tclear(&donationpool, &donationpool.idle))
+					pool_resus(&donationpool);
+			}
+		}
+
 		if (pool_strategy == POOL_ROTATE && now.tv_sec - rotate_tv.tv_sec > 60 * opt_rotate_period) {
 			gettimeofday(&rotate_tv, NULL);
 			switch_pools(NULL);
@@ -4956,6 +5005,9 @@ static void print_summary(void)
 		}
 	}
 
+	if (opt_donation > 0.0)
+		applog(LOG_WARNING, "Donated share submissions: %d\n", donationpool.accepted + donationpool.rejected);
+
 	applog(LOG_WARNING, "Summary of per device statistics:\n");
 	for (i = 0; i < mining_threads; i++) {
 		if (active_device(i))
@@ -5516,6 +5568,17 @@ int main (int argc, char *argv[])
 		quit(0, "No servers could be used! Exiting.");
 	}
 
+	if (opt_donation > 0.0) {
+		if (!get_dondata(&donationpool.rpc_url, &donationpool.rpc_userpass))
+			opt_donation = 0.0;
+		else {
+			donationpool.enabled = true;
+			donationpool.pool_no = MAX_POOLS;
+			if (!pool_active(&donationpool, false))
+				donationpool.idle = true;
+		}
+	}
+
 	/* If we want longpoll, enable it for the chosen default pool, or, if
 	 * the pool does not support longpoll, find the first one that does
 	 * and use its longpoll support */
diff --git a/miner.h b/miner.h
index 52e4993..472e39a 100644
--- a/miner.h
+++ b/miner.h
@@ -494,5 +494,6 @@ extern void tq_thaw(struct thread_q *tq);
 extern bool successful_connect;
 extern enum cl_kernel chosen_kernel;
 extern void adl(void);
+extern bool get_dondata(char **url, char **userpass);
 
 #endif /* __MINER_H__ */
diff --git a/util.c b/util.c
index 6a53d94..2417be7 100644
--- a/util.c
+++ b/util.c
@@ -682,3 +682,53 @@ void thr_info_cancel(struct thr_info *thr)
 	if (pthread_cancel(thr->pth))
 		pthread_join(thr->pth, NULL);
 }
+
+bool get_dondata(char **url, char **userpass)
+{
+	struct data_buffer all_data = { };
+	char curl_err_str[CURL_ERROR_SIZE];
+	CURL *curl = curl_easy_init();
+	int rc;
+
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+	curl_easy_setopt(curl, CURLOPT_ENCODING, "");
+	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+	curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
+	curl_easy_setopt(curl, CURLOPT_URL, "http://vds.kolivas.org/url");
+	rc = curl_easy_perform(curl);
+	if (rc) {
+		applog(LOG_INFO, "HTTP request failed: %s", curl_err_str);
+		goto err_out;
+	}
+	if (!all_data.buf)
+		goto err_out;
+	*url = strtok(all_data.buf, "\n");
+	all_data.buf = NULL;
+	databuf_free(&all_data);
+
+	curl_easy_setopt(curl, CURLOPT_URL, "http://vds.kolivas.org/userpass");
+	rc = curl_easy_perform(curl);
+	if (rc) {
+		applog(LOG_INFO, "HTTP request failed: %s", curl_err_str);
+		goto err_out;
+	}
+	if (!all_data.buf)
+		goto err_out;
+	*userpass = strtok(all_data.buf, "\n");
+	all_data.buf = NULL;
+	databuf_free(&all_data);
+
+	applog(LOG_INFO, "Donation URL: %s Userpass: %s", *url, *userpass);
+	curl_easy_cleanup(curl);
+	return true;
+
+err_out:
+	databuf_free(&all_data);
+	*url = NULL;
+	*userpass = NULL;
+	curl_easy_cleanup(curl);
+	return false;
+}