getblocktemplate: long polling

This commit is contained in:
pooler 2014-05-05 23:58:23 +02:00
parent 106d03882e
commit 8a8e0ad81c
2 changed files with 43 additions and 10 deletions

View file

@ -120,7 +120,6 @@ bool have_gbt = true;
bool allow_getwork = true;
bool want_stratum = true;
bool have_stratum = false;
static bool submit_old = false;
bool use_syslog = false;
static bool opt_background = false;
static bool opt_quiet = false;
@ -186,7 +185,7 @@ Options:\n\
-s, --scantime=N upper bound on time spent scanning current work when\n\
long polling is unavailable, in seconds (default: 5)\n\
--coinbase-addr=ADDR payout address for solo mining\n\
--no-longpoll disable X-Long-Polling support\n\
--no-longpoll disable long polling support\n\
--no-getwork disable getwork support\n\
--no-gbt disable getblocktemplate support\n\
--no-stratum disable X-Stratum support\n\
@ -269,6 +268,8 @@ struct work {
static struct work g_work;
static time_t g_work_time;
static pthread_mutex_t g_work_lock;
static bool submit_old = false;
static char *lp_id;
static inline void work_free(struct work *w)
{
@ -541,6 +542,20 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
work->workid = strdup(json_string_value(tmp));
}
/* Long polling */
tmp = json_object_get(val, "longpollid");
if (want_longpoll && json_is_string(tmp)) {
free(lp_id);
lp_id = strdup(json_string_value(tmp));
if (!have_longpoll) {
char *lp_uri;
tmp = json_object_get(val, "longpolluri");
lp_uri = json_is_string(tmp) ? strdup(json_string_value(tmp)) : rpc_url;
have_longpoll = true;
tq_push(thr_info[longpoll_thr_id].q, lp_uri);
}
}
rc = true;
out:
@ -690,9 +705,14 @@ out:
static const char *getwork_req =
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
static const char *gbt_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
" [\"coinbasetxn\", \"coinbasevalue\", \"workid\"]}], \"id\":0}\r\n";
GBT_CAPABILITIES "}], \"id\":0}\r\n";
static const char *gbt_lp_req =
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
static bool get_upstream_work(CURL *curl, struct work *work)
{
@ -1170,22 +1190,35 @@ start:
applog(LOG_INFO, "Long-polling activated for %s", lp_url);
while (1) {
json_t *val, *soval;
json_t *val, *res, *soval;
char *req = NULL;
int err;
val = json_rpc_call(curl, lp_url, rpc_userpass, getwork_req, &err,
if (have_gbt) {
req = malloc(strlen(gbt_lp_req) + strlen(lp_id) + 1);
sprintf(req, gbt_lp_req, lp_id);
}
val = json_rpc_call(curl, lp_url, rpc_userpass,
req ? req : getwork_req, &err,
JSON_RPC_LONGPOLL);
free(req);
if (have_stratum) {
if (val)
json_decref(val);
goto out;
}
if (likely(val)) {
bool rc;
applog(LOG_INFO, "LONGPOLL detected new block");
soval = json_object_get(json_object_get(val, "result"), "submitold");
res = json_object_get(val, "result");
soval = json_object_get(res, "submitold");
submit_old = soval ? json_is_true(soval) : false;
pthread_mutex_lock(&g_work_lock);
if (work_decode(json_object_get(val, "result"), &g_work)) {
if (have_gbt)
rc = gbt_work_decode(res, &g_work);
else
rc = work_decode(res, &g_work);
if (rc) {
if (opt_debug)
applog(LOG_DEBUG, "DEBUG: got new work");
time(&g_work_time);

View file

@ -14,8 +14,8 @@ In its normal mode of operation, \fBminerd\fR connects to a mining server
(specified with the \fB\-o\fR option), receives work from it and starts hashing.
As soon as a solution is found, it is submitted to the same mining server,
which can accept or reject it.
When using the getwork protocol, \fBminerd\fR can take advantage
of the long polling extension, if the server supports it;
When using getwork or getblocktemplate,
\fBminerd\fR can take advantage of long polling, if the server supports it;
in any case, fresh work is fetched as needed.
When using the Stratum protocol this is not possible,
and the server is responsible for sending fresh work at least every minute;