Browse Source

stratum: handle optional mining.set_extranonce

allow pools to switch more coins without reconnect

Tested ok on a nicehash x11 pool

Signed-off-by: Tanguy Pruvot <tanguy.pruvot@gmail.com>
master
Tanguy Pruvot 10 years ago
parent
commit
5ddc8de9da
  1. 108
      util.cpp

108
util.cpp

@ -906,11 +906,53 @@ static const char *get_stratum_session_id(json_t *val)
return NULL; 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) bool stratum_subscribe(struct stratum_ctx *sctx)
{ {
char *s, *sret = NULL; char *s, *sret = NULL;
const char *sid, *xnonce1; const char *sid;
int xn2_size;
json_t *val = NULL, *res_val, *err_val; json_t *val = NULL, *res_val, *err_val;
json_error_t err; json_error_t err;
bool ret = false, retry = false; bool ret = false, retry = false;
@ -927,7 +969,7 @@ start:
if (!stratum_send_line(sctx, s)) if (!stratum_send_line(sctx, s))
goto out; goto out;
if (!socket_full(sctx->sock, 30)) { if (!socket_full(sctx->sock, 10)) {
applog(LOG_ERR, "stratum_subscribe timed out"); applog(LOG_ERR, "stratum_subscribe timed out");
goto out; goto out;
} }
@ -959,33 +1001,20 @@ start:
goto out; goto out;
} }
// session id
sid = get_stratum_session_id(res_val); sid = get_stratum_session_id(res_val);
if (opt_debug && !sid) if (opt_debug && sid)
applog(LOG_DEBUG, "Failed to get Stratum session id"); applog(LOG_DEBUG, "Stratum session id: %s", sid);
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;
}
pthread_mutex_lock(&sctx->work_lock); pthread_mutex_lock(&sctx->work_lock);
if (sctx->session_id)
free(sctx->session_id); free(sctx->session_id);
free(sctx->xnonce1);
sctx->session_id = sid ? strdup(sid) : NULL; 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; sctx->next_diff = 1.0;
pthread_mutex_unlock(&sctx->work_lock); pthread_mutex_unlock(&sctx->work_lock);
if (opt_debug && sid) // sid is param 1, extranonce params are 2 and 3
applog(LOG_DEBUG, "Stratum session id: %s", sctx->session_id); stratum_parse_extranonce(sctx, res_val, 1);
ret = true; ret = true;
@ -1034,6 +1063,9 @@ bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *p
goto out; 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"); res_val = json_object_get(val, "result");
err_val = json_object_get(val, "error"); 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; 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: out:
free(s); free(s);
if (val) if (val)
@ -1304,6 +1364,10 @@ bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
ret = stratum_set_difficulty(sctx, params); ret = stratum_set_difficulty(sctx, params);
goto out; goto out;
} }
if (!strcasecmp(method, "mining.set_extranonce")) {
ret = stratum_parse_extranonce(sctx, params, 0);
goto out;
}
if (!strcasecmp(method, "client.reconnect")) { if (!strcasecmp(method, "client.reconnect")) {
ret = stratum_reconnect(sctx, params); ret = stratum_reconnect(sctx, params);
goto out; goto out;

Loading…
Cancel
Save