diff --git a/util.cpp b/util.cpp index fee037a..c6555dc 100644 --- a/util.cpp +++ b/util.cpp @@ -906,11 +906,53 @@ static const char *get_stratum_session_id(json_t *val) return NULL; } +static bool stratum_parse_extranonce(struct stratum_ctx *sctx, json_t *params, int pndx) +{ + const char* xnonce1; + int xn2_size; + + xnonce1 = json_string_value(json_array_get(params, pndx)); + if (!xnonce1) { + applog(LOG_ERR, "Failed to get extranonce1"); + goto out; + } + xn2_size = json_integer_value(json_array_get(params, pndx+1)); + if (!xn2_size) { + applog(LOG_ERR, "Failed to get extranonce2_size"); + goto out; + } + if (xn2_size < 2 || xn2_size > 16) { + applog(LOG_INFO, "Failed to get valid n2size in parse_extranonce"); + goto out; + } + + pthread_mutex_lock(&sctx->work_lock); + if (sctx->xnonce1) + free(sctx->xnonce1); + sctx->xnonce1_size = strlen(xnonce1) / 2; + sctx->xnonce1 = (uchar*) calloc(1, sctx->xnonce1_size); + if (unlikely(!sctx->xnonce1)) { + applog(LOG_ERR, "Failed to alloc xnonce1"); + pthread_mutex_unlock(&sctx->work_lock); + goto out; + } + hex2bin(sctx->xnonce1, xnonce1, sctx->xnonce1_size); + sctx->xnonce2_size = xn2_size; + pthread_mutex_unlock(&sctx->work_lock); + + if (pndx == 0 && opt_debug) /* pool dynamic change */ + applog(LOG_DEBUG, "Stratum set nonce %s with extranonce2 size=%d", + xnonce1, xn2_size); + + return true; +out: + return false; +} + bool stratum_subscribe(struct stratum_ctx *sctx) { char *s, *sret = NULL; - const char *sid, *xnonce1; - int xn2_size; + const char *sid; json_t *val = NULL, *res_val, *err_val; json_error_t err; bool ret = false, retry = false; @@ -927,7 +969,7 @@ start: if (!stratum_send_line(sctx, s)) goto out; - if (!socket_full(sctx->sock, 30)) { + if (!socket_full(sctx->sock, 10)) { applog(LOG_ERR, "stratum_subscribe timed out"); goto out; } @@ -959,33 +1001,20 @@ start: goto out; } + // session id sid = get_stratum_session_id(res_val); - if (opt_debug && !sid) - applog(LOG_DEBUG, "Failed to get Stratum session id"); - xnonce1 = json_string_value(json_array_get(res_val, 1)); - if (!xnonce1) { - applog(LOG_ERR, "Failed to get extranonce1"); - goto out; - } - xn2_size = json_integer_value(json_array_get(res_val, 2)); - if (!xn2_size) { - applog(LOG_ERR, "Failed to get extranonce2_size"); - goto out; - } + if (opt_debug && sid) + applog(LOG_DEBUG, "Stratum session id: %s", sid); pthread_mutex_lock(&sctx->work_lock); - free(sctx->session_id); - free(sctx->xnonce1); + if (sctx->session_id) + free(sctx->session_id); sctx->session_id = sid ? strdup(sid) : NULL; - sctx->xnonce1_size = strlen(xnonce1) / 2; - sctx->xnonce1 = (uchar*) malloc(sctx->xnonce1_size); - hex2bin(sctx->xnonce1, xnonce1, sctx->xnonce1_size); - sctx->xnonce2_size = xn2_size; sctx->next_diff = 1.0; pthread_mutex_unlock(&sctx->work_lock); - if (opt_debug && sid) - applog(LOG_DEBUG, "Stratum session id: %s", sctx->session_id); + // sid is param 1, extranonce params are 2 and 3 + stratum_parse_extranonce(sctx, res_val, 1); ret = true; @@ -1034,6 +1063,9 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p goto out; } + if (json_integer_value(json_object_get(val, "id")) != 2) { + applog(LOG_WARNING, "Stratum answer id is not correct!"); + } res_val = json_object_get(val, "result"); err_val = json_object_get(val, "error"); @@ -1045,6 +1077,34 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p ret = true; + // subscribe to extranonce (optional) + sprintf(s, "{\"id\": 3, \"method\": \"mining.extranonce.subscribe\", \"params\": []}"); + + if (!stratum_send_line(sctx, s)) + goto out; + + if (!socket_full(sctx->sock, 3)) { + applog(LOG_ERR, "stratum extranonce subscribe timed out"); + goto out; + } + + sret = stratum_recv_line(sctx); + if (sret) { + json_t *extra = JSON_LOADS(sret, &err); + free(sret); + if (!extra) { + applog(LOG_WARNING, "JSON decode failed(%d): %s", err.line, err.text); + } else { + if (json_integer_value(json_object_get(extra, "id")) != 3) { + applog(LOG_WARNING, "Stratum answer id is not correct!"); + } + res_val = json_object_get(extra, "result"); + if (opt_debug && (!res_val || json_is_false(res_val))) + applog(LOG_DEBUG, "extranonce subscribe not supported"); + json_decref(extra); + } + } + out: free(s); if (val) @@ -1304,6 +1364,10 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s) ret = stratum_set_difficulty(sctx, params); goto out; } + if (!strcasecmp(method, "mining.set_extranonce")) { + ret = stratum_parse_extranonce(sctx, params, 0); + goto out; + } if (!strcasecmp(method, "client.reconnect")) { ret = stratum_reconnect(sctx, params); goto out;