Browse Source

Properly detect pool protocol

Luke Dashjr 13 years ago
parent
commit
b155e61286
2 changed files with 45 additions and 16 deletions
  1. 44 16
      miner.c
  2. 1 0
      miner.h

+ 44 - 16
miner.c

@@ -2310,13 +2310,12 @@ static void get_benchmark_work(struct work *work)
 	work->pool = pools[0];
 }
 
-static char *prepare_rpc_req(struct work *work)
+static char *prepare_rpc_req(struct work *work, enum pool_protocol proto)
 {
 	// FIXME: error checking
-	struct pool *pool = work->pool;
 	char *rpc_req;
 
-	switch (pool->proto) {
+	switch (proto) {
 		case PLP_GETWORK:
 			work->tmpl = NULL;
 			return strdup(getwork_rpc_req);
@@ -2328,19 +2327,30 @@ static char *prepare_rpc_req(struct work *work)
 			rpc_req = json_dumps(req, 0);
 			json_decref(req);
 			return rpc_req;
+		default:
+			return false;
 	}
-	return false;
 }
 
-static bool pool_proto_fallback(struct pool *pool)
+static const char *pool_protocol_name(enum pool_protocol proto)
 {
-	switch (pool->proto) {
+	switch (proto) {
 		case PLP_GETBLOCKTEMPLATE:
-			applog(LOG_WARNING, "Pool %u failed getblocktemplate request; falling back to getwork protocol", pool->pool_no);
-			pool->proto = PLP_GETWORK;
-			return true;
+			return "getblocktemplate";
+		case PLP_GETWORK:
+			return "getwork";
 		default:
-			return false;
+			return "UNKNOWN";
+	}
+}
+
+static enum pool_protocol pool_protocol_fallback(enum pool_protocol proto)
+{
+	switch (proto) {
+		case PLP_GETBLOCKTEMPLATE:
+			return PLP_GETWORK;
+		default:
+			return PLP_NONE;
 	}
 }
 
@@ -2352,11 +2362,12 @@ static bool get_upstream_work(struct work *work, CURL *curl)
 	json_t *val = NULL;
 	bool rc = false;
 	char *url;
+	enum pool_protocol proto;
 
 	char *rpc_req;
 
 tryagain:
-	rpc_req = prepare_rpc_req(work);
+	rpc_req = prepare_rpc_req(work, pool->proto);
 
 	applog(LOG_DEBUG, "DBG: sending %s get RPC call: %s", pool->rpc_url, rpc_req);
 
@@ -2374,7 +2385,9 @@ tryagain:
 		rc = work_decode(json_object_get(val, "result"), work);
 		if (unlikely(!rc))
 			applog(LOG_DEBUG, "Failed to decode work in get_upstream_work");
-	} else if (pool_proto_fallback(pool)) {
+	} else if (PLP_NONE != (proto = pool_protocol_fallback(pool->proto))) {
+		applog(LOG_WARNING, "Pool %u failed getblocktemplate request; falling back to getwork protocol", pool->pool_no);
+		pool->proto = proto;
 		goto tryagain;
 	} else
 		applog(LOG_DEBUG, "Failed json_rpc_call in get_upstream_work");
@@ -4454,6 +4467,7 @@ static bool pool_active(struct pool *pool, bool pinging)
 	int rolltime;
 	char *rpc_req;
 	struct work *work;
+	enum pool_protocol proto;
 
 	curl = curl_easy_init();
 	if (unlikely(!curl)) {
@@ -4463,10 +4477,10 @@ static bool pool_active(struct pool *pool, bool pinging)
 
 	work = make_work();
 	work->pool = pool;
-	pool->proto = PLP_GETBLOCKTEMPLATE;
+	proto = PLP_GETBLOCKTEMPLATE;
 
 tryagain:
-	rpc_req = prepare_rpc_req(work);
+	rpc_req = prepare_rpc_req(work, proto);
 
 	applog(LOG_INFO, "Testing pool %s", pool->rpc_url);
 	val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req,
@@ -4474,8 +4488,13 @@ tryagain:
 
 	if (val) {
 		bool rc;
+		json_t *res;
 
-		rc = work_decode(json_object_get(val, "result"), work);
+		res = json_object_get(val, "result");
+		if ((!json_is_object(res)) || (proto == PLP_GETBLOCKTEMPLATE && !json_object_get(res, "bits")))
+			goto badwork;
+
+		rc = work_decode(res, work);
 		if (rc) {
 			applog(LOG_DEBUG, "Successfully retrieved and deciphered work from pool %u %s",
 			       pool->pool_no, pool->rpc_url);
@@ -4489,9 +4508,13 @@ tryagain:
 			ret = true;
 			gettimeofday(&pool->tv_idle, NULL);
 		} else {
+badwork:
 			applog(LOG_DEBUG, "Successfully retrieved but FAILED to decipher work from pool %u %s",
 			       pool->pool_no, pool->rpc_url);
+			if (PLP_NONE != (proto = pool_protocol_fallback(proto)))
+				goto tryagain;
 			free_work(work);
+			goto out;
 		}
 		json_decref(val);
 
@@ -4529,7 +4552,12 @@ tryagain:
 			if (unlikely(pthread_create(&pool->longpoll_thread, NULL, longpoll_thread, (void *)pool)))
 				quit(1, "Failed to create pool longpoll thread");
 		}
-	} else if (pool_proto_fallback(pool)) {
+
+		if (proto != pool->proto) {
+			pool->proto = proto;
+			applog(LOG_INFO, "Selected %s protocol for pool %u", pool_protocol_name(proto), pool->pool_no);
+		}
+	} else if (PLP_NONE != (proto = pool_protocol_fallback(proto))) {
 		goto tryagain;
 	} else {
 		free_work(work);

+ 1 - 0
miner.h

@@ -796,6 +796,7 @@ enum pool_enable {
 };
 
 enum pool_protocol {
+	PLP_NONE,
 	PLP_GETWORK,
 	PLP_GETBLOCKTEMPLATE,
 };