Browse Source

Merge branch 'auto_solomine' into bfgminer

Luke Dashjr 11 years ago
parent
commit
a7b81b68b6
2 changed files with 116 additions and 17 deletions
  1. 95 17
      miner.c
  2. 21 0
      util.h

+ 95 - 17
miner.c

@@ -128,11 +128,8 @@ static bool want_longpoll = true;
 static bool want_gbt = true;
 static bool want_getwork = true;
 #if BLKMAKER_VERSION > 1
-struct _cbscript_t {
-	char *data;
-	size_t sz;
-};
-static struct _cbscript_t opt_coinbase_script;
+static bool have_at_least_one_getcbaddr;
+static bytes_t opt_coinbase_script = BYTES_INIT;
 static uint32_t template_nonce;
 #endif
 #if BLKMAKER_VERSION > 0
@@ -1078,6 +1075,14 @@ struct pool *add_pool(void)
 	return pool;
 }
 
+static
+void pool_set_uri(struct pool * const pool, char * const uri)
+{
+	pool->rpc_url = uri;
+	if (uri_get_param_bool(uri, "getcbaddr", false))
+		have_at_least_one_getcbaddr = true;
+}
+
 /* Pool variant of test and set */
 static bool pool_tset(struct pool *pool, bool *var)
 {
@@ -1188,7 +1193,8 @@ char *set_strdup(const char *arg, char **p)
 }
 
 #if BLKMAKER_VERSION > 1
-static char *set_b58addr(const char *arg, struct _cbscript_t *p)
+static
+char *set_b58addr(const char * const arg, bytes_t * const b)
 {
 	size_t scriptsz = blkmk_address_to_script(NULL, 0, arg);
 	if (!scriptsz)
@@ -1198,9 +1204,7 @@ static char *set_b58addr(const char *arg, struct _cbscript_t *p)
 		free(script);
 		return "Failed to convert address to script";
 	}
-	free(p->data);
-	p->data = script;
-	p->sz = scriptsz;
+	bytes_assimilate_raw(b, script, scriptsz, scriptsz);
 	return NULL;
 }
 #endif
@@ -1444,7 +1448,7 @@ bool detect_stratum(struct pool *pool, char *url)
 		return false;
 
 	if (!strncasecmp(url, "stratum+tcp://", 14)) {
-		pool->rpc_url = strdup(url);
+		pool_set_uri(pool, strdup(url));
 		pool->has_stratum = true;
 		pool->stratum_url = pool->sockaddr_url;
 		return true;
@@ -1476,7 +1480,7 @@ static void setup_url(struct pool *pool, char *arg)
 		if (!httpinput)
 			quit(1, "Failed to malloc httpinput");
 		sprintf(httpinput, "http://%s", arg);
-		pool->rpc_url = httpinput;
+		pool_set_uri(pool, httpinput);
 	}
 }
 
@@ -2834,6 +2838,72 @@ void work_set_simple_ntime_roll_limit(struct work * const work, const int ntime_
 	set_simple_ntime_roll_limit(&work->ntime_roll_limits, upk_u32be(work->data, 0x44), ntime_roll);
 }
 
+static
+void refresh_bitcoind_address(const bool fresh)
+{
+	if (!have_at_least_one_getcbaddr)
+		return;
+	
+	char getcbaddr_req[60];
+	CURL *curl = NULL;
+	json_t *json, *j2;
+	const char *s, *s2;
+	bytes_t newscript = BYTES_INIT;
+	
+	snprintf(getcbaddr_req, sizeof(getcbaddr_req), "{\"method\":\"get%saddress\",\"id\":0,\"params\":[\"BFGMiner\"]}", fresh ? "new" : "account");
+	
+	for (int i = 0; i < total_pools; ++i)
+	{
+		struct pool * const pool = pools[i];
+		if (!uri_get_param_bool(pool->rpc_url, "getcbaddr", false))
+			continue;
+		
+		applog(LOG_DEBUG, "Refreshing coinbase address from pool %d", pool->pool_no);
+		if (!curl)
+		{
+			curl = curl_easy_init();
+			if (unlikely(!curl))
+			{
+				applogfail(LOG_ERR, "curl_easy_init");
+				break;
+			}
+		}
+		json = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, getcbaddr_req, false, false, NULL, pool, true);
+		j2 = json_object_get(json, "error");
+		if (unlikely(!json_is_null(j2)))
+		{
+			char *estr = NULL;
+			applog(LOG_WARNING, "Error %cetting coinbase address from pool %d: %s", 'g', pool->pool_no, json_string_value(j2) ?: (estr = json_dumps_ANY(j2, JSON_ENSURE_ASCII | JSON_SORT_KEYS)));
+			free(estr);
+			continue;
+		}
+		s = bfg_json_obj_string(json, "result", NULL);
+		if (unlikely(!s))
+		{
+			applog(LOG_WARNING, "Error %cetting coinbase address from pool %d: %s", 'g', pool->pool_no, "(return value was not a String)");
+			continue;
+		}
+		s2 = set_b58addr(s, &newscript);
+		if (unlikely(s2))
+		{
+			applog(LOG_WARNING, "Error %cetting coinbase address from pool %d: %s", 's', pool->pool_no, s2);
+			continue;
+		}
+		if (bytes_eq(&newscript, &opt_coinbase_script))
+		{
+			applog(LOG_DEBUG, "Pool %d returned coinbase address already in use (%s)", pool->pool_no, s2);
+			break;
+		}
+		bytes_assimilate(&opt_coinbase_script, &newscript);
+		applog(LOG_NOTICE, "Now using coinbase address %s, provided by pool %d", s, pool->pool_no);
+		break;
+	}
+	
+	bytes_free(&newscript);
+	if (curl)
+		curl_easy_cleanup(curl);
+}
+
 static double target_diff(const unsigned char *);
 
 #define GBT_XNONCESZ (sizeof(uint32_t))
@@ -2869,14 +2939,20 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
 		}
 		work->rolltime = blkmk_time_left(tmpl, tv_now.tv_sec);
 #if BLKMAKER_VERSION > 1
-		if (opt_coinbase_script.sz)
+		if ((!tmpl->cbtxn) && !bytes_len(&opt_coinbase_script))
+		{
+			// We are about to fail here because we lack a coinbase transaction
+			// Try to get an address from bitcoind to use to avoid this
+			refresh_bitcoind_address(false);
+		}
+		if (bytes_len(&opt_coinbase_script))
 		{
 			bool newcb;
 #if BLKMAKER_VERSION > 2
-			blkmk_init_generation2(tmpl, opt_coinbase_script.data, opt_coinbase_script.sz, &newcb);
+			blkmk_init_generation2(tmpl, bytes_buf(&opt_coinbase_script), bytes_len(&opt_coinbase_script), &newcb);
 #else
 			newcb = !tmpl->cbtxn;
-			blkmk_init_generation(tmpl, opt_coinbase_script.data, opt_coinbase_script.sz);
+			blkmk_init_generation(tmpl, bytes_buf(&opt_coinbase_script), bytes_len(&opt_coinbase_script));
 #endif
 			if (newcb)
 			{
@@ -4876,6 +4952,7 @@ void setup_benchmark_pool()
 	
 	pool->rpc_url = malloc(255);
 	strcpy(pool->rpc_url, "Benchmark");
+	pool_set_uri(pool, pool->rpc_url);
 	pool->rpc_user = pool->rpc_url;
 	pool->rpc_pass = pool->rpc_url;
 	enable_pool(pool);
@@ -5016,7 +5093,7 @@ static char *prepare_rpc_req2(struct work *work, enum pool_protocol proto, const
 				goto gbtfail;
 			caps |= GBT_LONGPOLL;
 #if BLKMAKER_VERSION > 1
-			if (opt_coinbase_script.sz)
+			if (bytes_len(&opt_coinbase_script) || have_at_least_one_getcbaddr)
 				caps |= GBT_CBVALUE;
 #endif
 			json_t *req = blktmpl_request_jansson(caps, lpid);
@@ -5703,6 +5780,7 @@ void work_check_for_block(struct work * const work)
 		found_blocks++;
 		work->mandatory = true;
 		applog(LOG_NOTICE, "Found block for pool %d!", work->pool->pool_no);
+		refresh_bitcoind_address(true);
 	}
 }
 
@@ -8719,7 +8797,7 @@ tryagain:
 
 		applog(LOG_NOTICE, "Switching pool %d %s to %s", pool->pool_no, pool->rpc_url, pool->stratum_url);
 		if (!pool->rpc_url)
-			pool->rpc_url = strdup(pool->stratum_url);
+			pool_set_uri(pool, strdup(pool->stratum_url));
 		pool->has_stratum = true;
 
 		}
@@ -10739,7 +10817,7 @@ bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char
 {
 	size_t siz;
 
-	pool->rpc_url = url;
+	pool_set_uri(pool, url);
 	pool->rpc_user = user;
 	pool->rpc_pass = pass;
 	siz = strlen(pool->rpc_user) + strlen(pool->rpc_pass) + 2;

+ 21 - 0
util.h

@@ -448,6 +448,14 @@ ssize_t bytes_find(const bytes_t * const b, const uint8_t needle)
 	return -1;
 }
 
+static inline
+bool bytes_eq(const bytes_t * const a, const bytes_t * const b)
+{
+	if (a->sz != b->sz)
+		return false;
+	return !memcmp(a->buf, b->buf, a->sz);
+}
+
 extern void _bytes_alloc_failure(size_t);
 
 static inline
@@ -519,6 +527,19 @@ void bytes_cpy(bytes_t *dst, const bytes_t *src)
 	memcpy(dst->buf, src->buf, dst->sz);
 }
 
+// Efficiently moves the data from src to dst, emptying src in the process
+static inline
+void bytes_assimilate(bytes_t * const dst, bytes_t * const src)
+{
+	void * const buf = dst->buf;
+	const size_t allocsz = dst->allocsz;
+	*dst = *src;
+	*src = (bytes_t){
+		.buf = buf,
+		.allocsz = allocsz,
+	};
+}
+
 static inline
 void bytes_assimilate_raw(bytes_t * const b, void * const buf, const size_t bufsz, const size_t buflen)
 {