diff --git a/src/ckpool.c b/src/ckpool.c index 4e85521e..be13551e 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2017 Con Kolivas + * Copyright 2014-2018 Con Kolivas * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -980,7 +980,7 @@ bool send_json_msg(connsock_t *cs, const json_t *json_msg) /* Decode a string that should have a json message and return just the contents * of the result key or NULL. */ -static json_t *json_result(json_t *val) +json_t *json_result(json_t *val) { json_t *res_val = NULL, *err_val; @@ -1005,7 +1005,7 @@ static json_t *json_result(json_t *val) } /* Return the error value if one exists */ -static json_t *json_errval(json_t *val) +json_t *json_errval(json_t *val) { json_t *err_val = json_object_get(val, "error"); diff --git a/src/ckpool.h b/src/ckpool.h index 51ab760a..e519176e 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -371,6 +371,8 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req); json_t *json_rpc_response(connsock_t *cs, const char *rpc_req); void json_rpc_msg(connsock_t *cs, const char *rpc_req); bool send_json_msg(connsock_t *cs, const json_t *json_msg); +json_t *json_result(json_t *val); +json_t *json_errval(json_t *val); json_t *json_msg_result(const char *msg, json_t **res_val, json_t **err_val); bool json_get_string(char **store, const json_t *val, const char *res); diff --git a/src/generator.c b/src/generator.c index 61cf4464..17c1130f 100644 --- a/src/generator.c +++ b/src/generator.c @@ -115,6 +115,8 @@ struct proxy_instance { int nonce1len; int nonce2len; + uint32_t version_mask; + tv_t last_message; double diff; @@ -1317,6 +1319,35 @@ static void send_notify(ckpool_t *ckp, proxy_instance_t *proxi, notify_instance_ send_diff(ckp, proxi); } +static void parse_configure(ckpool_t *ckp, proxy_instance_t *proxy, json_t *val) +{ + bool vroll = false; + json_t *res_val; + const char *buf; + + res_val = json_result(val); + if (!res_val) { + LOGDEBUG("Failed to find result response to mining.configure from proxy %d:%s", + proxy->id, proxy->url); + return; + } + vroll = json_is_true(json_object_get(res_val, "version-rolling")); + if (!vroll) { + LOGINFO("No version rolling from compatible proxy %d:%s", proxy->id, + proxy->url); + return; + } + buf = json_string_value(json_object_get(res_val, "version-rolling.mask")); + if (!buf || !strlen(buf)) { + LOGNOTICE("Invalid version-rolling.mask from proxy %d:%s", proxy->id, + proxy->url); + return; + } + sscanf(buf, "%x", &proxy->version_mask); + LOGINFO("Got vmask %s from proxy %d:%d %s", buf, proxy->id, proxy->subid, proxy->url); + stratum_set_proxy_vmask(ckp, proxy->id, proxy->subid, proxy->version_mask); +} + static bool parse_method(ckpool_t *ckp, proxy_instance_t *proxi, const char *msg) { json_t *val = NULL, *method, *err_val, *params; @@ -1346,6 +1377,9 @@ static bool parse_method(ckpool_t *ckp, proxy_instance_t *proxi, const char *msg if (strstr(msg, "mining.suggest")) { LOGINFO("Unhandled suggest_diff from proxy %d:%s", proxi->id, proxi->url); ret = true; + } else if (strstr(msg, "version-rolling")) { + parse_configure(ckp, proxi, val); + ret = true; } else LOGDEBUG("Failed to find method in json for parse_method"); goto out; @@ -2020,6 +2054,30 @@ static void suggest_diff(ckpool_t *ckp, connsock_t *cs, proxy_instance_t *proxy) * if it fails upstream. */ } +static void request_configure(ckpool_t *ckp, connsock_t *cs, proxy_instance_t *proxy) +{ + json_t *req; + bool ret; + + JSON_CPACK(req, "{s:i,s:s, s:[]}", + "id", 40, + "method", "mining.configure", + "params"); + ret = send_json_msg(cs, req); + json_decref(req); + if (!ret) { + LOGNOTICE("Proxy %d:%d %s failed to send message in request_configure", + proxy->id, proxy->subid, proxy->url); + if (cs->fd > 0) { + epoll_ctl(proxy->epfd, EPOLL_CTL_DEL, cs->fd, NULL); + Close(cs->fd); + } + } + /* Response will be parsed by receiver since response can be wildly + * variable. */ +} + + /* Upon failing connnect, subscribe, or auth, back off on the next attempt. * This function should be called on the parent proxy */ static void proxy_backoff(proxy_instance_t *proxy) @@ -2104,6 +2162,9 @@ static bool proxy_alive(ckpool_t *ckp, proxy_instance_t *proxi, connsock_t *cs, proxy_backoff(parent); goto out; } + /* Put a request for mining configure to see if the upstream pool + * supports version_mask */ + request_configure(ckp, cs, proxi); parent->auth_status = STATUS_SUCCESS; proxi->authorised = ret = true; parent->backoff = 0; diff --git a/src/stratifier.c b/src/stratifier.c index ca4fa258..0beea46a 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -309,6 +309,8 @@ struct proxy_base { bool subscribed; bool notified; + uint32_t version_mask; + int64_t clients; /* Incrementing client count */ int64_t max_clients; /* Maximum number of clients per subproxy */ int64_t bound_clients; /* Currently actively bound clients */ @@ -3047,6 +3049,15 @@ out: json_decref(val); } +void stratum_set_proxy_vmask(ckpool_t *ckp, int id, int subid, uint32_t version_mask) +{ + proxy_t *proxy; + + proxy = existing_subproxy(ckp->sdata, id, subid); + proxy->version_mask = version_mask; + LOGWARNING("Stratum Proxy %d:%d had version mask set to %x", id, subid, version_mask); +} + static void stratum_send_diff(sdata_t *sdata, const stratum_instance_t *client); static void update_diff(ckpool_t *ckp, const char *cmd) @@ -5708,6 +5719,20 @@ static void stratum_send_diff(sdata_t *sdata, const stratum_instance_t *client) stratum_add_send(sdata, json_msg, client->id, SM_DIFF); } +#if 0 +/* Needs to be entered with client holding a ref count. */ +static void stratum_send_version_mask(sdata_t *sdata, const stratum_instance_t *client) +{ + char version_str[12]; + json_t *json_msg; + + sprintf(version_str, "%08x", client->ckp->version_mask); + JSON_CPACK(json_msg, "{s[s]soss}", "params", version_str, "id", json_null(), + "method", "mining.set_version_mask"); + stratum_add_send(sdata, json_msg, client->id, SM_VERSIONMASK); +} +#endif + /* Needs to be entered with client holding a ref count. */ static void stratum_send_message(sdata_t *sdata, const stratum_instance_t *client, const char *msg) { diff --git a/src/stratifier.h b/src/stratifier.h index cc201890..1809c023 100644 --- a/src/stratifier.h +++ b/src/stratifier.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2017 Con Kolivas + * Copyright 2014-2018 Con Kolivas * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -86,6 +86,7 @@ struct genwork { json_t *json; /* getblocktemplate json */ }; +void stratum_set_proxy_vmask(ckpool_t *ckp, int id, int subid, uint32_t version_mask); void parse_remote_txns(ckpool_t *ckp, const json_t *val); #define parse_upstream_txns(ckp, val) parse_remote_txns(ckp, val) void parse_upstream_auth(ckpool_t *ckp, json_t *val);