From aaaf38722210048e7a5e80d97872661d48de13c9 Mon Sep 17 00:00:00 2001 From: elbandi Date: Thu, 24 Apr 2014 13:05:02 +0200 Subject: [PATCH 1/6] handle mining.set_extranonce method --- util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/util.c b/util.c index 97ad9a79..36866e5c 100644 --- a/util.c +++ b/util.c @@ -1664,6 +1664,48 @@ static bool parse_diff(struct pool *pool, json_t *val) return true; } +static bool parse_extranonce(struct pool *pool, json_t *val) +{ + char s[RBUFSIZE], *nonce1; + int n2size; + int id = json_integer_value(json_object_get(val, "id")); + json_t *params = json_object_get(val, "params"); + + if (!id) + return false; + + nonce1 = json_array_string(params, 0); + if (!nonce1) { +// applog(LOG_INFO, "Failed to get nonce1 in "); + return false; + } + n2size = json_integer_value(json_array_get(params, 1)); + if (!n2size) { +// applog(LOG_INFO, "Failed to get n2size in "); + free(nonce1); + return false; + } + + cg_wlock(&pool->data_lock); + pool->nonce1 = nonce1; + pool->n1_len = strlen(nonce1) / 2; + free(pool->nonce1bin); + pool->nonce1bin = (unsigned char *)calloc(pool->n1_len, 1); + if (unlikely(!pool->nonce1bin)) + quithere(1, "Failed to calloc pool->nonce1bin"); + hex2bin(pool->nonce1bin, pool->nonce1, pool->n1_len); + pool->n2size = n2size; + cg_wunlock(&pool->data_lock); + + sprintf(s, "{\"id\": %d, \"result\": \"true\", \"error\": null}", id); + if (!stratum_send(pool, s, strlen(s))) + return false; + + applog(LOG_NOTICE, "%s coin change requested", get_pool_name(pool)); + + return true; +} + static void __suspend_stratum(struct pool *pool) { clear_sockbuf(pool); @@ -1807,6 +1849,12 @@ bool parse_method(struct pool *pool, char *s) return ret; } + if (!strncasecmp(buf, "mining.set_extranonce", 21) && parse_extranonce(pool, val)) { + ret = true; + json_decref(val); + return ret; + } + if (!strncasecmp(buf, "client.reconnect", 16) && parse_reconnect(pool, params)) { ret = true; json_decref(val); From b742ced4ebc243410bf6d8a75a852cdb25212be6 Mon Sep 17 00:00:00 2001 From: elbandi Date: Thu, 24 Apr 2014 14:18:38 +0200 Subject: [PATCH 2/6] subscribe for mining.extranonce --- sgminer.c | 11 ++++++++++- util.c | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/sgminer.c b/sgminer.c index 980b4e39..3bdfb030 100644 --- a/sgminer.c +++ b/sgminer.c @@ -5204,6 +5204,15 @@ static bool parse_stratum_response(struct pool *pool, char *s) id = json_integer_value(id_val); + if (err_val && !json_is_null(err_val)) { + char *ss; + ss = (char *)json_string_value(json_array_get(err_val, 1)); + if (strcmp(ss, "Method 'subscribe' not found for service 'mining.extranonce'") == 0) { + applog(LOG_INFO, "Cannot subscribe to mining.extranonce on %s", get_pool_name(pool)); + goto out; + } + } + mutex_lock(&sshare_lock); HASH_FIND_INT(stratum_shares, &id, sshare); if (sshare) { @@ -5673,7 +5682,7 @@ retry_stratum: bool init = pool_tset(pool, &pool->stratum_init); if (!init) { - bool ret = initiate_stratum(pool) && auth_stratum(pool); + bool ret = initiate_stratum(pool) && auth_stratum(pool) && subscribe_extranonce(pool); if (ret) init_stratum_threads(pool); diff --git a/util.c b/util.c index 36866e5c..0d08b585 100644 --- a/util.c +++ b/util.c @@ -1876,6 +1876,22 @@ bool parse_method(struct pool *pool, char *s) return ret; } +bool subscribe_extranonce(struct pool *pool) +{ + char s[RBUFSIZE]; + bool ret = false; + + sprintf(s, "{\"id\": %d, \"method\": \"mining.extranonce.subscribe\", \"params\": []}", + swork_id++); + + if (!stratum_send(pool, s, strlen(s))) + return ret; + + ret = true; + applog(LOG_INFO, "Stratum extranonce subscribe for %s", get_pool_name(pool)); + return ret; +} + bool auth_stratum(struct pool *pool) { json_t *val = NULL, *res_val, *err_val; @@ -2506,6 +2522,8 @@ bool restart_stratum(struct pool *pool) return false; if (!auth_stratum(pool)) return false; + if (!subscribe_extranonce(pool)) + return false; return true; } From 4ad62b9a78a1adfbff7850e2265076ad6e696199 Mon Sep 17 00:00:00 2001 From: elbandi Date: Thu, 24 Apr 2014 15:44:50 +0200 Subject: [PATCH 3/6] Allow disable extranonce subscribe --- miner.h | 1 + sgminer.c | 8 ++++++-- util.c | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/miner.h b/miner.h index 7db088fd..be1be447 100644 --- a/miner.h +++ b/miner.h @@ -1078,6 +1078,7 @@ extern int nDevs; extern int hw_errors; extern bool use_syslog; extern bool opt_quiet; +extern bool opt_extranonce_subscribe; extern struct thr_info *control_thr; extern struct thr_info **mining_thr; extern struct cgpu_info gpus[MAX_GPUDEVICES]; diff --git a/sgminer.c b/sgminer.c index 3bdfb030..0765cba8 100644 --- a/sgminer.c +++ b/sgminer.c @@ -151,6 +151,7 @@ bool opt_api_network; bool opt_delaynet; bool opt_disable_pool; bool opt_disable_client_reconnect = false; +bool opt_extranonce_subscribe = true; static bool no_work; bool opt_worktime; #if defined(HAVE_LIBCURL) && defined(CURL_HAS_KEEPALIVE) @@ -1327,6 +1328,9 @@ static struct opt_table opt_config_table[] = { OPT_WITHOUT_ARG("--no-submit-stale", opt_set_invbool, &opt_submit_stale, "Don't submit shares if they are detected as stale"), + OPT_WITHOUT_ARG("--no-extranonce-subscribe", + opt_set_invbool, &opt_extranonce_subscribe, + "Disable 'extranonce' stratum subscribe"), OPT_WITH_ARG("--pass|-p", set_pass, NULL, NULL, "Password for bitcoin JSON-RPC server"), @@ -5207,7 +5211,7 @@ static bool parse_stratum_response(struct pool *pool, char *s) if (err_val && !json_is_null(err_val)) { char *ss; ss = (char *)json_string_value(json_array_get(err_val, 1)); - if (strcmp(ss, "Method 'subscribe' not found for service 'mining.extranonce'") == 0) { + if (opt_extranonce_subscribe && strcmp(ss, "Method 'subscribe' not found for service 'mining.extranonce'") == 0) { applog(LOG_INFO, "Cannot subscribe to mining.extranonce on %s", get_pool_name(pool)); goto out; } @@ -5682,7 +5686,7 @@ retry_stratum: bool init = pool_tset(pool, &pool->stratum_init); if (!init) { - bool ret = initiate_stratum(pool) && auth_stratum(pool) && subscribe_extranonce(pool); + bool ret = initiate_stratum(pool) && auth_stratum(pool) && (!opt_extranonce_subscribe || subscribe_extranonce(pool)); if (ret) init_stratum_threads(pool); diff --git a/util.c b/util.c index 0d08b585..5de9669c 100644 --- a/util.c +++ b/util.c @@ -2522,7 +2522,7 @@ bool restart_stratum(struct pool *pool) return false; if (!auth_stratum(pool)) return false; - if (!subscribe_extranonce(pool)) + if (opt_extranonce_subscribe && !subscribe_extranonce(pool)) return false; return true; From 281bcd75e92cd9824a3b62f90821c6c5ddb89083 Mon Sep 17 00:00:00 2001 From: elbandi Date: Thu, 24 Apr 2014 16:34:00 +0200 Subject: [PATCH 4/6] Send subscribe request before auth --- sgminer.c | 2 +- util.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/sgminer.c b/sgminer.c index 0765cba8..4b3bf7cf 100644 --- a/sgminer.c +++ b/sgminer.c @@ -5686,7 +5686,7 @@ retry_stratum: bool init = pool_tset(pool, &pool->stratum_init); if (!init) { - bool ret = initiate_stratum(pool) && auth_stratum(pool) && (!opt_extranonce_subscribe || subscribe_extranonce(pool)); + bool ret = initiate_stratum(pool) && (!opt_extranonce_subscribe || subscribe_extranonce(pool)) && auth_stratum(pool); if (ret) init_stratum_threads(pool); diff --git a/util.c b/util.c index 5de9669c..c6179c1f 100644 --- a/util.c +++ b/util.c @@ -1878,7 +1878,9 @@ bool parse_method(struct pool *pool, char *s) bool subscribe_extranonce(struct pool *pool) { - char s[RBUFSIZE]; + json_t *val = NULL, *res_val, *err_val; + char s[RBUFSIZE], *sret = NULL; + json_error_t err; bool ret = false; sprintf(s, "{\"id\": %d, \"method\": \"mining.extranonce.subscribe\", \"params\": []}", @@ -1887,8 +1889,54 @@ bool subscribe_extranonce(struct pool *pool) if (!stratum_send(pool, s, strlen(s))) return ret; + /* Parse all data in the queue and anything left should be auth */ + while (42) { + if (!socket_full(pool, DEFAULT_SOCKWAIT)) { + applog(LOG_DEBUG, "Timed out waiting for response extranonce.subscribe"); + /* some pool doesnt send anything, so this is normal */ + ret = true; + goto out; + } + + sret = recv_line(pool); + if (!sret) + return ret; + if (parse_method(pool, sret)) + free(sret); + else + break; + } + + val = JSON_LOADS(sret, &err); + free(sret); + res_val = json_object_get(val, "result"); + err_val = json_object_get(val, "error"); + + if (!res_val || json_is_false(res_val) || (err_val && !json_is_null(err_val))) { + char *ss; + + if (err_val) { + ss = (char *)json_string_value(json_array_get(err_val, 1)); + if (opt_extranonce_subscribe && strcmp(ss, "Method 'subscribe' not found for service 'mining.extranonce'") == 0) { + applog(LOG_INFO, "Cannot subscribe to mining.extranonce on %s", get_pool_name(pool)); + ret = true; + goto out; + } + ss = json_dumps(err_val, JSON_INDENT(3)); + } + else + ss = strdup("(unknown reason)"); + applog(LOG_INFO, "%s JSON stratum auth failed: %s", get_pool_name(pool), ss); + free(ss); + + goto out; + } + ret = true; applog(LOG_INFO, "Stratum extranonce subscribe for %s", get_pool_name(pool)); + +out: + json_decref(val); return ret; } @@ -2520,10 +2568,10 @@ bool restart_stratum(struct pool *pool) suspend_stratum(pool); if (!initiate_stratum(pool)) return false; - if (!auth_stratum(pool)) - return false; if (opt_extranonce_subscribe && !subscribe_extranonce(pool)) return false; + if (!auth_stratum(pool)) + return false; return true; } From e1dcbfab15db334620a8eca8f14c5cd2265a46b7 Mon Sep 17 00:00:00 2001 From: elbandi Date: Thu, 24 Apr 2014 20:38:37 +0200 Subject: [PATCH 5/6] Change mining.set_extranonce method as stratum notification --- util.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/util.c b/util.c index c6179c1f..8f0bcbf5 100644 --- a/util.c +++ b/util.c @@ -1668,18 +1668,13 @@ static bool parse_extranonce(struct pool *pool, json_t *val) { char s[RBUFSIZE], *nonce1; int n2size; - int id = json_integer_value(json_object_get(val, "id")); - json_t *params = json_object_get(val, "params"); - - if (!id) - return false; - nonce1 = json_array_string(params, 0); + nonce1 = json_array_string(val, 0); if (!nonce1) { // applog(LOG_INFO, "Failed to get nonce1 in "); return false; } - n2size = json_integer_value(json_array_get(params, 1)); + n2size = json_integer_value(json_array_get(val, 1)); if (!n2size) { // applog(LOG_INFO, "Failed to get n2size in "); free(nonce1); @@ -1697,10 +1692,6 @@ static bool parse_extranonce(struct pool *pool, json_t *val) pool->n2size = n2size; cg_wunlock(&pool->data_lock); - sprintf(s, "{\"id\": %d, \"result\": \"true\", \"error\": null}", id); - if (!stratum_send(pool, s, strlen(s))) - return false; - applog(LOG_NOTICE, "%s coin change requested", get_pool_name(pool)); return true; @@ -1849,7 +1840,7 @@ bool parse_method(struct pool *pool, char *s) return ret; } - if (!strncasecmp(buf, "mining.set_extranonce", 21) && parse_extranonce(pool, val)) { + if (!strncasecmp(buf, "mining.set_extranonce", 21) && parse_extranonce(pool, params)) { ret = true; json_decref(val); return ret; From 75a86fbf1049c707e2a67b4661427551c99f44d3 Mon Sep 17 00:00:00 2001 From: Elbandi Date: Thu, 24 Apr 2014 20:57:09 +0200 Subject: [PATCH 6/6] Set extranonce.subscribe timeout to 2sec --- util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util.c b/util.c index 8f0bcbf5..ce9c122a 100644 --- a/util.c +++ b/util.c @@ -1882,7 +1882,7 @@ bool subscribe_extranonce(struct pool *pool) /* Parse all data in the queue and anything left should be auth */ while (42) { - if (!socket_full(pool, DEFAULT_SOCKWAIT)) { + if (!socket_full(pool, DEFAULT_SOCKWAIT / 30)) { applog(LOG_DEBUG, "Timed out waiting for response extranonce.subscribe"); /* some pool doesnt send anything, so this is normal */ ret = true;