]> Git Repo - cpuminer-multi.git/blame - util.c
Add S3 algo
[cpuminer-multi.git] / util.c
CommitLineData
b089cc9f
LJ
1/*
2 * Copyright 2010 Jeff Garzik
6a5cae3d 3 * Copyright 2012 Luke Dashjr
b089cc9f
LJ
4 * Copyright 2012-2014 pooler
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version. See COPYING for more details.
10 */
11
12#define _GNU_SOURCE
13#include "cpuminer-config.h"
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <ctype.h>
18#include <stdarg.h>
19#include <string.h>
20#include <stdbool.h>
21#include <inttypes.h>
6a5cae3d
TP
22#include <limits.h>
23#include <errno.h>
b089cc9f
LJ
24#include <unistd.h>
25#include <jansson.h>
26#include <curl/curl.h>
27#include <time.h>
28#if defined(WIN32)
29#include <winsock2.h>
30#include <mstcpip.h>
588f5d90 31#include "compat/winansi.h"
b089cc9f 32#else
b089cc9f
LJ
33#include <sys/socket.h>
34#include <netinet/in.h>
35#include <netinet/tcp.h>
36#endif
37#include "compat.h"
38#include "miner.h"
39#include "elist.h"
40
41struct data_buffer {
42 void *buf;
43 size_t len;
44};
45
46struct upload_buffer {
47 const void *buf;
48 size_t len;
49 size_t pos;
50};
51
52struct header_info {
53 char *lp_path;
54 char *reason;
55 char *stratum_url;
56};
57
58struct tq_ent {
59 void *data;
60 struct list_head q_node;
61};
62
63struct thread_q {
64 struct list_head q;
65
66 bool frozen;
67
68 pthread_mutex_t mutex;
69 pthread_cond_t cond;
70};
71
72void applog(int prio, const char *fmt, ...)
73{
74 va_list ap;
75
76 va_start(ap, fmt);
77
78#ifdef HAVE_SYSLOG_H
79 if (use_syslog) {
80 va_list ap2;
81 char *buf;
82 int len;
c64468ee
TP
83
84 /* custom colors to syslog prio */
85 if (prio > LOG_DEBUG) {
86 switch (prio) {
87 case LOG_BLUE: prio = LOG_NOTICE; break;
88 }
89 }
90
b089cc9f
LJ
91 va_copy(ap2, ap);
92 len = vsnprintf(NULL, 0, fmt, ap2) + 1;
93 va_end(ap2);
94 buf = alloca(len);
95 if (vsnprintf(buf, len, fmt, ap) >= 0)
96 syslog(prio, "%s", buf);
97 }
98#else
99 if (0) {}
100#endif
101 else {
c64468ee 102 const char* color = "";
b089cc9f
LJ
103 char *f;
104 int len;
105 time_t now;
106 struct tm tm, *tm_p;
107
108 time(&now);
109
110 pthread_mutex_lock(&applog_lock);
111 tm_p = localtime(&now);
f34c5672 112 memcpy(&tm, tm_p, sizeof(struct tm));
b089cc9f
LJ
113 pthread_mutex_unlock(&applog_lock);
114
c64468ee
TP
115 switch (prio) {
116 case LOG_ERR: color = CL_RED; break;
117 case LOG_WARNING: color = CL_YLW; break;
118 case LOG_NOTICE: color = CL_WHT; break;
119 case LOG_INFO: color = ""; break;
ccccf3ba 120 case LOG_DEBUG: color = CL_GRY; break;
c64468ee
TP
121
122 case LOG_BLUE:
123 prio = LOG_NOTICE;
124 color = CL_CYN;
125 break;
126 }
127 if (!use_colors)
128 color = "";
129
588f5d90
TP
130 len = 64 + (int) strlen(fmt) + 2;
131 f = (char*) malloc(len);
c64468ee 132 sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
b089cc9f
LJ
133 tm.tm_year + 1900,
134 tm.tm_mon + 1,
135 tm.tm_mday,
136 tm.tm_hour,
137 tm.tm_min,
138 tm.tm_sec,
c64468ee
TP
139 color,
140 fmt,
141 use_colors ? CL_N : ""
142 );
b089cc9f
LJ
143 pthread_mutex_lock(&applog_lock);
144 vfprintf(stderr, f, ap); /* atomic write to stderr */
145 fflush(stderr);
588f5d90 146 free(f),
b089cc9f
LJ
147 pthread_mutex_unlock(&applog_lock);
148 }
149 va_end(ap);
150}
151
6a5cae3d
TP
152/* Modify the representation of integer numbers which would cause an overflow
153 * so that they are treated as floating-point numbers.
154 * This is a hack to overcome the limitations of some versions of Jansson. */
155static char *hack_json_numbers(const char *in)
156{
157 char *out;
158 int i, off, intoff;
159 bool in_str, in_int;
160
588f5d90 161 out = (char*) calloc(2 * strlen(in) + 1, 1);
6a5cae3d
TP
162 if (!out)
163 return NULL;
164 off = intoff = 0;
165 in_str = in_int = false;
166 for (i = 0; in[i]; i++) {
167 char c = in[i];
168 if (c == '"') {
169 in_str = !in_str;
170 } else if (c == '\\') {
171 out[off++] = c;
172 if (!in[++i])
173 break;
174 } else if (!in_str && !in_int && isdigit(c)) {
175 intoff = off;
176 in_int = true;
177 } else if (in_int && !isdigit(c)) {
178 if (c != '.' && c != 'e' && c != 'E' && c != '+' && c != '-') {
179 in_int = false;
180 if (off - intoff > 4) {
181 char *end;
182#if JSON_INTEGER_IS_LONG_LONG
183 errno = 0;
184 strtoll(out + intoff, &end, 10);
185 if (!*end && errno == ERANGE) {
186#else
187 long l;
188 errno = 0;
189 l = strtol(out + intoff, &end, 10);
190 if (!*end && (errno == ERANGE || l > INT_MAX)) {
191#endif
192 out[off++] = '.';
193 out[off++] = '0';
194 }
195 }
196 }
197 }
198 out[off++] = in[i];
199 }
200 return out;
201}
202
b089cc9f
LJ
203static void databuf_free(struct data_buffer *db)
204{
205 if (!db)
206 return;
207
208 free(db->buf);
209
210 memset(db, 0, sizeof(*db));
211}
212
213static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
214 void *user_data)
215{
588f5d90 216 struct data_buffer *db = (struct data_buffer *) user_data;
b089cc9f
LJ
217 size_t len = size * nmemb;
218 size_t oldlen, newlen;
219 void *newmem;
220 static const unsigned char zero = 0;
221
222 oldlen = db->len;
223 newlen = oldlen + len;
224
225 newmem = realloc(db->buf, newlen + 1);
226 if (!newmem)
227 return 0;
228
229 db->buf = newmem;
230 db->len = newlen;
588f5d90
TP
231 memcpy((uchar*) db->buf + oldlen, ptr, len);
232 memcpy((uchar*) db->buf + newlen, &zero, 1); /* null terminate */
b089cc9f
LJ
233
234 return len;
235}
236
237static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
238 void *user_data)
239{
588f5d90 240 struct upload_buffer *ub = (struct upload_buffer *) user_data;
b089cc9f
LJ
241 int len = size * nmemb;
242
243 if (len > ub->len - ub->pos)
244 len = ub->len - ub->pos;
245
246 if (len) {
588f5d90 247 memcpy(ptr, ((uchar*)ub->buf) + ub->pos, len);
b089cc9f
LJ
248 ub->pos += len;
249 }
250
251 return len;
252}
253
254#if LIBCURL_VERSION_NUM >= 0x071200
255static int seek_data_cb(void *user_data, curl_off_t offset, int origin)
256{
588f5d90 257 struct upload_buffer *ub = (struct upload_buffer *) user_data;
b089cc9f
LJ
258
259 switch (origin) {
260 case SEEK_SET:
588f5d90 261 ub->pos = (size_t) offset;
b089cc9f
LJ
262 break;
263 case SEEK_CUR:
588f5d90 264 ub->pos += (size_t) offset;
b089cc9f
LJ
265 break;
266 case SEEK_END:
588f5d90 267 ub->pos = ub->len + (size_t) offset;
b089cc9f
LJ
268 break;
269 default:
270 return 1; /* CURL_SEEKFUNC_FAIL */
271 }
272
273 return 0; /* CURL_SEEKFUNC_OK */
274}
275#endif
276
277static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
278{
588f5d90 279 struct header_info *hi = (struct header_info *) user_data;
b089cc9f
LJ
280 size_t remlen, slen, ptrlen = size * nmemb;
281 char *rem, *val = NULL, *key = NULL;
282 void *tmp;
283
588f5d90
TP
284 val = (char*) calloc(1, ptrlen);
285 key = (char*) calloc(1, ptrlen);
b089cc9f
LJ
286 if (!key || !val)
287 goto out;
288
289 tmp = memchr(ptr, ':', ptrlen);
290 if (!tmp || (tmp == ptr)) /* skip empty keys / blanks */
291 goto out;
588f5d90 292 slen = (char*)tmp - (char*)ptr;
b089cc9f
LJ
293 if ((slen + 1) == ptrlen) /* skip key w/ no value */
294 goto out;
295 memcpy(key, ptr, slen); /* store & nul term key */
296 key[slen] = 0;
297
588f5d90 298 rem = (char*)ptr + slen + 1; /* trim value's leading whitespace */
b089cc9f
LJ
299 remlen = ptrlen - slen - 1;
300 while ((remlen > 0) && (isspace(*rem))) {
301 remlen--;
302 rem++;
303 }
304
305 memcpy(val, rem, remlen); /* store value, trim trailing ws */
306 val[remlen] = 0;
307 while ((*val) && (isspace(val[strlen(val) - 1]))) {
308 val[strlen(val) - 1] = 0;
309 }
b089cc9f
LJ
310
311 if (!strcasecmp("X-Long-Polling", key)) {
312 hi->lp_path = val; /* steal memory reference */
313 val = NULL;
314 }
315
316 if (!strcasecmp("X-Reject-Reason", key)) {
317 hi->reason = val; /* steal memory reference */
318 val = NULL;
319 }
320
321 if (!strcasecmp("X-Stratum", key)) {
322 hi->stratum_url = val; /* steal memory reference */
323 val = NULL;
324 }
325
326out:
327 free(key);
328 free(val);
329 return ptrlen;
330}
331
332#if LIBCURL_VERSION_NUM >= 0x070f06
333static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd,
334 curlsocktype purpose)
335{
336 int keepalive = 1;
337 int tcp_keepcnt = 3;
338 int tcp_keepidle = 50;
339 int tcp_keepintvl = 50;
340
341#ifndef WIN32
342 if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
343 sizeof(keepalive))))
344 return 1;
345#ifdef __linux
346 if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT,
347 &tcp_keepcnt, sizeof(tcp_keepcnt))))
348 return 1;
349 if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE,
350 &tcp_keepidle, sizeof(tcp_keepidle))))
351 return 1;
352 if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL,
353 &tcp_keepintvl, sizeof(tcp_keepintvl))))
354 return 1;
355#endif /* __linux */
356#ifdef __APPLE_CC__
357 if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
358 &tcp_keepintvl, sizeof(tcp_keepintvl))))
359 return 1;
360#endif /* __APPLE_CC__ */
361#else /* WIN32 */
362 struct tcp_keepalive vals;
363 vals.onoff = 1;
364 vals.keepalivetime = tcp_keepidle * 1000;
365 vals.keepaliveinterval = tcp_keepintvl * 1000;
366 DWORD outputBytes;
367 if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals),
368 NULL, 0, &outputBytes, NULL, NULL)))
369 return 1;
370#endif /* WIN32 */
371
372 return 0;
373}
374#endif
375
376json_t *json_rpc_call(CURL *curl, const char *url,
377 const char *userpass, const char *rpc_req,
378 int *curl_err, int flags)
379{
380 json_t *val, *err_val, *res_val;
381 int rc;
382 long http_rc;
383 struct data_buffer all_data = {0};
384 struct upload_buffer upload_data;
6a5cae3d 385 char *json_buf;
b089cc9f
LJ
386 json_error_t err;
387 struct curl_slist *headers = NULL;
388 char len_hdr[64];
389 char curl_err_str[CURL_ERROR_SIZE];
390 long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 30;
391 struct header_info hi = {0};
392
393 /* it is assumed that 'curl' is freshly [re]initialized at this pt */
394
395 if (opt_protocol)
396 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
397 curl_easy_setopt(curl, CURLOPT_URL, url);
398 if (opt_cert)
399 curl_easy_setopt(curl, CURLOPT_CAINFO, opt_cert);
400 curl_easy_setopt(curl, CURLOPT_ENCODING, "");
401 curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
402 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
403 curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
404 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
405 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
406 curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
407 curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
408#if LIBCURL_VERSION_NUM >= 0x071200
409 curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &seek_data_cb);
410 curl_easy_setopt(curl, CURLOPT_SEEKDATA, &upload_data);
411#endif
412 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
413 if (opt_redirect)
414 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
415 curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
416 curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
417 curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
418 if (opt_proxy) {
419 curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy);
420 curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type);
421 }
422 if (userpass) {
423 curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
424 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
425 }
426#if LIBCURL_VERSION_NUM >= 0x070f06
427 if (flags & JSON_RPC_LONGPOLL)
428 curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
429#endif
430 curl_easy_setopt(curl, CURLOPT_POST, 1);
431
432 if (opt_protocol)
433 applog(LOG_DEBUG, "JSON protocol request:\n%s\n", rpc_req);
434
435 upload_data.buf = rpc_req;
436 upload_data.len = strlen(rpc_req);
437 upload_data.pos = 0;
438 sprintf(len_hdr, "Content-Length: %lu",
439 (unsigned long) upload_data.len);
440
441 headers = curl_slist_append(headers, "Content-Type: application/json");
442 headers = curl_slist_append(headers, len_hdr);
443 headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
444 headers = curl_slist_append(headers, "X-Mining-Extensions: midstate");
30f9ef7e 445 //headers = curl_slist_append(headers, "Accept:"); /* disable Accept hdr*/
446 //headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
b089cc9f
LJ
447
448 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
449
450 rc = curl_easy_perform(curl);
451 if (curl_err != NULL)
452 *curl_err = rc;
453 if (rc) {
454 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
455 if (!((flags & JSON_RPC_LONGPOLL) && rc == CURLE_OPERATION_TIMEDOUT) &&
456 !((flags & JSON_RPC_QUIET_404) && http_rc == 404))
457 applog(LOG_ERR, "HTTP request failed: %s", curl_err_str);
6a5cae3d
TP
458 if (curl_err && (flags & JSON_RPC_QUIET_404) && http_rc == 404)
459 *curl_err = CURLE_OK;
b089cc9f
LJ
460 goto err_out;
461 }
462
463 /* If X-Stratum was found, activate Stratum */
464 if (want_stratum && hi.stratum_url &&
465 !strncasecmp(hi.stratum_url, "stratum+tcp://", 14)) {
466 have_stratum = true;
467 tq_push(thr_info[stratum_thr_id].q, hi.stratum_url);
468 hi.stratum_url = NULL;
469 }
470
471 /* If X-Long-Polling was found, activate long polling */
6a5cae3d
TP
472 if (!have_longpoll && want_longpoll && hi.lp_path && !have_gbt &&
473 allow_getwork && !have_stratum) {
b089cc9f
LJ
474 have_longpoll = true;
475 tq_push(thr_info[longpoll_thr_id].q, hi.lp_path);
476 hi.lp_path = NULL;
477 }
478
479 if (!all_data.buf) {
480 applog(LOG_ERR, "Empty data received in json_rpc_call.");
481 goto err_out;
482 }
483
588f5d90 484 json_buf = hack_json_numbers((char*) all_data.buf);
6a5cae3d
TP
485 errno = 0; /* needed for Jansson < 2.1 */
486 val = JSON_LOADS(json_buf, &err);
487 free(json_buf);
b089cc9f
LJ
488 if (!val) {
489 applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
490 goto err_out;
491 }
492
493 if (opt_protocol) {
494 char *s = json_dumps(val, JSON_INDENT(3));
495 applog(LOG_DEBUG, "JSON protocol response:\n%s", s);
496 free(s);
497 }
498
6a5cae3d 499 /* JSON-RPC valid response returns a 'result' and a null 'error'. */
b089cc9f
LJ
500 res_val = json_object_get(val, "result");
501 err_val = json_object_get(val, "error");
502
6a5cae3d
TP
503 if (!res_val || (err_val && !json_is_null(err_val)
504 && !(flags & JSON_RPC_IGNOREERR))) {
505
b089cc9f
LJ
506 char *s;
507
508 if (err_val)
509 s = json_dumps(err_val, JSON_INDENT(3));
510 else
511 s = strdup("(unknown reason)");
512
513 applog(LOG_ERR, "JSON-RPC call failed: %s", s);
514
515 free(s);
516
517 goto err_out;
518 }
519
520 if (hi.reason)
521 json_object_set_new(val, "reject-reason", json_string(hi.reason));
522
523 databuf_free(&all_data);
524 curl_slist_free_all(headers);
525 curl_easy_reset(curl);
526 return val;
527
528err_out:
529 free(hi.lp_path);
530 free(hi.reason);
531 free(hi.stratum_url);
532 databuf_free(&all_data);
533 curl_slist_free_all(headers);
534 curl_easy_reset(curl);
535 return NULL;
536}
537
6a5cae3d 538void bin2hex(char *s, const unsigned char *p, size_t len)
b089cc9f
LJ
539{
540 int i;
b089cc9f
LJ
541 for (i = 0; i < len; i++)
542 sprintf(s + (i * 2), "%02x", (unsigned int) p[i]);
6a5cae3d 543}
b089cc9f 544
6a5cae3d
TP
545char *abin2hex(const unsigned char *p, size_t len)
546{
588f5d90 547 char *s = (char*) malloc((len * 2) + 1);
6a5cae3d
TP
548 if (!s)
549 return NULL;
550 bin2hex(s, p, len);
b089cc9f
LJ
551 return s;
552}
553
554bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
555{
556 char hex_byte[3];
557 char *ep;
558
559 hex_byte[2] = '\0';
560
561 while (*hexstr && len) {
562 if (!hexstr[1]) {
563 applog(LOG_ERR, "hex2bin str truncated");
564 return false;
565 }
566 hex_byte[0] = hexstr[0];
567 hex_byte[1] = hexstr[1];
568 *p = (unsigned char) strtol(hex_byte, &ep, 16);
569 if (*ep) {
570 applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte);
571 return false;
572 }
573 p++;
574 hexstr += 2;
575 len--;
576 }
577
15f243e7
TP
578 return(!len) ? true : false;
579/* return (len == 0 && *hexstr == 0) ? true : false; */
b089cc9f
LJ
580}
581
6a5cae3d
TP
582int varint_encode(unsigned char *p, uint64_t n)
583{
584 int i;
585 if (n < 0xfd) {
586 p[0] = n;
587 return 1;
588 }
589 if (n <= 0xffff) {
590 p[0] = 0xfd;
591 p[1] = n & 0xff;
592 p[2] = n >> 8;
593 return 3;
594 }
595 if (n <= 0xffffffff) {
596 p[0] = 0xfe;
597 for (i = 1; i < 5; i++) {
598 p[i] = n & 0xff;
599 n >>= 8;
600 }
601 return 5;
602 }
603 p[0] = 0xff;
604 for (i = 1; i < 9; i++) {
605 p[i] = n & 0xff;
606 n >>= 8;
607 }
608 return 9;
609}
610
611static const char b58digits[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
612
613static bool b58dec(unsigned char *bin, size_t binsz, const char *b58)
614{
615 size_t i, j;
616 uint64_t t;
617 uint32_t c;
618 uint32_t *outi;
619 size_t outisz = (binsz + 3) / 4;
620 int rem = binsz % 4;
621 uint32_t remmask = 0xffffffff << (8 * rem);
622 size_t b58sz = strlen(b58);
623 bool rc = false;
624
588f5d90 625 outi = (uint32_t *) calloc(outisz, sizeof(*outi));
6a5cae3d
TP
626
627 for (i = 0; i < b58sz; ++i) {
628 for (c = 0; b58digits[c] != b58[i]; c++)
629 if (!b58digits[c])
630 goto out;
631 for (j = outisz; j--; ) {
632 t = (uint64_t)outi[j] * 58 + c;
633 c = t >> 32;
634 outi[j] = t & 0xffffffff;
635 }
636 if (c || outi[0] & remmask)
637 goto out;
638 }
639
640 j = 0;
641 switch (rem) {
642 case 3:
643 *(bin++) = (outi[0] >> 16) & 0xff;
644 case 2:
645 *(bin++) = (outi[0] >> 8) & 0xff;
646 case 1:
647 *(bin++) = outi[0] & 0xff;
648 ++j;
649 default:
650 break;
651 }
652 for (; j < outisz; ++j) {
653 be32enc((uint32_t *)bin, outi[j]);
654 bin += sizeof(uint32_t);
655 }
656
657 rc = true;
658out:
659 free(outi);
660 return rc;
661}
662
663static int b58check(unsigned char *bin, size_t binsz, const char *b58)
664{
665 unsigned char buf[32];
666 int i;
667
668 sha256d(buf, bin, binsz - 4);
669 if (memcmp(&bin[binsz - 4], buf, 4))
670 return -1;
671
672 /* Check number of zeros is correct AFTER verifying checksum
673 * (to avoid possibility of accessing the string beyond the end) */
674 for (i = 0; bin[i] == '\0' && b58[i] == '1'; ++i);
675 if (bin[i] == '\0' || b58[i] == '1')
676 return -3;
677
678 return bin[0];
679}
680
681size_t address_to_script(unsigned char *out, size_t outsz, const char *addr)
682{
683 unsigned char addrbin[25];
684 int addrver;
685 size_t rv;
686
687 if (!b58dec(addrbin, sizeof(addrbin), addr))
688 return 0;
689 addrver = b58check(addrbin, sizeof(addrbin), addr);
690 if (addrver < 0)
691 return 0;
692 switch (addrver) {
693 case 5: /* Bitcoin script hash */
694 case 196: /* Testnet script hash */
695 if (outsz < (rv = 23))
696 return rv;
697 out[ 0] = 0xa9; /* OP_HASH160 */
698 out[ 1] = 0x14; /* push 20 bytes */
699 memcpy(&out[2], &addrbin[1], 20);
700 out[22] = 0x87; /* OP_EQUAL */
701 return rv;
702 default:
703 if (outsz < (rv = 25))
704 return rv;
705 out[ 0] = 0x76; /* OP_DUP */
706 out[ 1] = 0xa9; /* OP_HASH160 */
707 out[ 2] = 0x14; /* push 20 bytes */
708 memcpy(&out[3], &addrbin[1], 20);
709 out[23] = 0x88; /* OP_EQUALVERIFY */
710 out[24] = 0xac; /* OP_CHECKSIG */
711 return rv;
712 }
713}
714
b089cc9f
LJ
715/* Subtract the `struct timeval' values X and Y,
716 storing the result in RESULT.
717 Return 1 if the difference is negative, otherwise 0. */
718int timeval_subtract(struct timeval *result, struct timeval *x,
719 struct timeval *y)
720{
721 /* Perform the carry for the later subtraction by updating Y. */
722 if (x->tv_usec < y->tv_usec) {
723 int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
724 y->tv_usec -= 1000000 * nsec;
725 y->tv_sec += nsec;
726 }
727 if (x->tv_usec - y->tv_usec > 1000000) {
728 int nsec = (x->tv_usec - y->tv_usec) / 1000000;
729 y->tv_usec += 1000000 * nsec;
730 y->tv_sec -= nsec;
731 }
732
733 /* Compute the time remaining to wait.
734 * `tv_usec' is certainly positive. */
735 result->tv_sec = x->tv_sec - y->tv_sec;
736 result->tv_usec = x->tv_usec - y->tv_usec;
737
738 /* Return 1 if result is negative. */
739 return x->tv_sec < y->tv_sec;
740}
741
742bool fulltest(const uint32_t *hash, const uint32_t *target)
743{
744 int i;
745 bool rc = true;
746
747 for (i = 7; i >= 0; i--) {
748 if (hash[i] > target[i]) {
749 rc = false;
750 break;
751 }
752 if (hash[i] < target[i]) {
753 rc = true;
754 break;
755 }
756 }
757
758 if (opt_debug) {
759 uint32_t hash_be[8], target_be[8];
6a5cae3d 760 char hash_str[65], target_str[65];
b089cc9f
LJ
761
762 for (i = 0; i < 8; i++) {
763 be32enc(hash_be + i, hash[7 - i]);
764 be32enc(target_be + i, target[7 - i]);
765 }
6a5cae3d
TP
766 bin2hex(hash_str, (unsigned char *)hash_be, 32);
767 bin2hex(target_str, (unsigned char *)target_be, 32);
b089cc9f
LJ
768
769 applog(LOG_DEBUG, "DEBUG: %s\nHash: %s\nTarget: %s",
770 rc ? "hash <= target"
771 : "hash > target (false positive)",
772 hash_str,
773 target_str);
b089cc9f
LJ
774 }
775
776 return rc;
777}
778
779void diff_to_target(uint32_t *target, double diff)
780{
781 uint64_t m;
782 int k;
783
784 for (k = 6; k > 0 && diff > 1.0; k--)
785 diff /= 4294967296.0;
588f5d90 786 m = (uint64_t)(4294901760.0 / diff);
b089cc9f
LJ
787 if (m == 0 && k == 6)
788 memset(target, 0xff, 32);
789 else {
790 memset(target, 0, 32);
791 target[k] = (uint32_t)m;
792 target[k + 1] = (uint32_t)(m >> 32);
793 }
794}
795
796#ifdef WIN32
797#define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK)
798#else
799#define socket_blocks() (errno == EAGAIN || errno == EWOULDBLOCK)
800#endif
801
802static bool send_line(curl_socket_t sock, char *s)
803{
804 ssize_t len, sent = 0;
805
806 len = strlen(s);
807 s[len++] = '\n';
808
809 while (len > 0) {
810 struct timeval timeout = {0, 0};
811 ssize_t n;
812 fd_set wd;
813
814 FD_ZERO(&wd);
815 FD_SET(sock, &wd);
816 if (select(sock + 1, NULL, &wd, NULL, &timeout) < 1)
817 return false;
818 n = send(sock, s + sent, len, 0);
819 if (n < 0) {
820 if (!socket_blocks())
821 return false;
822 n = 0;
823 }
824 sent += n;
825 len -= n;
826 }
827
828 return true;
829}
830
831bool stratum_send_line(struct stratum_ctx *sctx, char *s)
832{
833 bool ret = false;
834
835 if (opt_protocol)
836 applog(LOG_DEBUG, "> %s", s);
837
838 pthread_mutex_lock(&sctx->sock_lock);
839 ret = send_line(sctx->sock, s);
840 pthread_mutex_unlock(&sctx->sock_lock);
841
842 return ret;
843}
844
845static bool socket_full(curl_socket_t sock, int timeout)
846{
847 struct timeval tv;
848 fd_set rd;
849
850 FD_ZERO(&rd);
851 FD_SET(sock, &rd);
852 tv.tv_sec = timeout;
853 tv.tv_usec = 0;
854 if (select(sock + 1, &rd, NULL, NULL, &tv) > 0)
855 return true;
856 return false;
857}
858
859bool stratum_socket_full(struct stratum_ctx *sctx, int timeout)
860{
861 return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout);
862}
863
864#define RBUFSIZE 2048
865#define RECVSIZE (RBUFSIZE - 4)
866
867static void stratum_buffer_append(struct stratum_ctx *sctx, const char *s)
868{
588f5d90 869 size_t old, n;
b089cc9f
LJ
870
871 old = strlen(sctx->sockbuf);
588f5d90
TP
872 n = old + strlen(s) + 1;
873 if (n >= sctx->sockbuf_size) {
874 sctx->sockbuf_size = n + (RBUFSIZE - (n % RBUFSIZE));
875 sctx->sockbuf = (char*) realloc(sctx->sockbuf, sctx->sockbuf_size);
b089cc9f
LJ
876 }
877 strcpy(sctx->sockbuf + old, s);
878}
879
880char *stratum_recv_line(struct stratum_ctx *sctx)
881{
882 ssize_t len, buflen;
883 char *tok, *sret = NULL;
884
885 if (!strstr(sctx->sockbuf, "\n")) {
886 bool ret = true;
887 time_t rstart;
888
889 time(&rstart);
890 if (!socket_full(sctx->sock, 60)) {
891 applog(LOG_ERR, "stratum_recv_line timed out");
892 goto out;
893 }
894 do {
895 char s[RBUFSIZE];
896 ssize_t n;
897
898 memset(s, 0, RBUFSIZE);
899 n = recv(sctx->sock, s, RECVSIZE, 0);
900 if (!n) {
901 ret = false;
902 break;
903 }
904 if (n < 0) {
905 if (!socket_blocks() || !socket_full(sctx->sock, 1)) {
906 ret = false;
907 break;
908 }
909 } else
910 stratum_buffer_append(sctx, s);
911 } while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n"));
912
913 if (!ret) {
914 applog(LOG_ERR, "stratum_recv_line failed");
915 goto out;
916 }
917 }
918
919 buflen = strlen(sctx->sockbuf);
920 tok = strtok(sctx->sockbuf, "\n");
921 if (!tok) {
922 applog(LOG_ERR, "stratum_recv_line failed to parse a newline-terminated string");
923 goto out;
924 }
925 sret = strdup(tok);
926 len = strlen(sret);
927
928 if (buflen > len + 1)
929 memmove(sctx->sockbuf, sctx->sockbuf + len + 1, buflen - len + 1);
930 else
931 sctx->sockbuf[0] = '\0';
932
933out:
934 if (sret && opt_protocol)
935 applog(LOG_DEBUG, "< %s", sret);
936 return sret;
937}
938
939#if LIBCURL_VERSION_NUM >= 0x071101
940static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose,
941 struct curl_sockaddr *addr)
942{
588f5d90 943 curl_socket_t *sock = (curl_socket_t*) clientp;
b089cc9f
LJ
944 *sock = socket(addr->family, addr->socktype, addr->protocol);
945 return *sock;
946}
947#endif
948
949bool stratum_connect(struct stratum_ctx *sctx, const char *url)
950{
951 CURL *curl;
952 int rc;
953
954 pthread_mutex_lock(&sctx->sock_lock);
955 if (sctx->curl)
956 curl_easy_cleanup(sctx->curl);
957 sctx->curl = curl_easy_init();
958 if (!sctx->curl) {
959 applog(LOG_ERR, "CURL initialization failed");
960 pthread_mutex_unlock(&sctx->sock_lock);
961 return false;
962 }
963 curl = sctx->curl;
964 if (!sctx->sockbuf) {
588f5d90 965 sctx->sockbuf = (char*) calloc(RBUFSIZE, 1);
b089cc9f
LJ
966 sctx->sockbuf_size = RBUFSIZE;
967 }
968 sctx->sockbuf[0] = '\0';
969 pthread_mutex_unlock(&sctx->sock_lock);
970
971 if (url != sctx->url) {
972 free(sctx->url);
973 sctx->url = strdup(url);
974 }
975 free(sctx->curl_url);
588f5d90 976 sctx->curl_url = (char*) malloc(strlen(url));
b089cc9f
LJ
977 sprintf(sctx->curl_url, "http%s", strstr(url, "://"));
978
979 if (opt_protocol)
980 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
981 curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url);
982 curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
983 curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
984 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str);
985 curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
986 curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
987 if (opt_proxy) {
988 curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy);
989 curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type);
990 }
991 curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1);
992#if LIBCURL_VERSION_NUM >= 0x070f06
993 curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
994#endif
995#if LIBCURL_VERSION_NUM >= 0x071101
996 curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb);
997 curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock);
998#endif
999 curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
1000
1001 rc = curl_easy_perform(curl);
1002 if (rc) {
1003 applog(LOG_ERR, "Stratum connection failed: %s", sctx->curl_err_str);
1004 curl_easy_cleanup(curl);
1005 sctx->curl = NULL;
1006 return false;
1007 }
1008
1009#if LIBCURL_VERSION_NUM < 0x071101
1010 /* CURLINFO_LASTSOCKET is broken on Win64; only use it as a last resort */
1011 curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sctx->sock);
1012#endif
1013
1014 return true;
1015}
1016
1017void stratum_disconnect(struct stratum_ctx *sctx)
1018{
1019 pthread_mutex_lock(&sctx->sock_lock);
1020 if (sctx->curl) {
1021 curl_easy_cleanup(sctx->curl);
1022 sctx->curl = NULL;
1023 sctx->sockbuf[0] = '\0';
1024 }
1025 pthread_mutex_unlock(&sctx->sock_lock);
1026}
1027
1028static const char *get_stratum_session_id(json_t *val)
1029{
1030 json_t *arr_val;
1031 int i, n;
1032
1033 arr_val = json_array_get(val, 0);
1034 if (!arr_val || !json_is_array(arr_val))
1035 return NULL;
1036 n = json_array_size(arr_val);
1037 for (i = 0; i < n; i++) {
1038 const char *notify;
1039 json_t *arr = json_array_get(arr_val, i);
1040
1041 if (!arr || !json_is_array(arr))
1042 break;
1043 notify = json_string_value(json_array_get(arr, 0));
1044 if (!notify)
1045 continue;
1046 if (!strcasecmp(notify, "mining.notify"))
1047 return json_string_value(json_array_get(arr, 1));
1048 }
1049 return NULL;
1050}
1051
1052bool stratum_subscribe(struct stratum_ctx *sctx)
1053{
1054 char *s, *sret = NULL;
1055 const char *sid, *xnonce1;
1056 int xn2_size;
1057 json_t *val = NULL, *res_val, *err_val;
1058 json_error_t err;
1059 bool ret = false, retry = false;
1060
52eb8a13
TP
1061 if (jsonrpc_2)
1062 return true;
1063
b089cc9f 1064start:
588f5d90 1065 s = (char*) malloc(128 + (sctx->session_id ? strlen(sctx->session_id) : 0));
b089cc9f
LJ
1066 if (retry)
1067 sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": []}");
1068 else if (sctx->session_id)
1069 sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"" USER_AGENT "\", \"%s\"]}", sctx->session_id);
1070 else
1071 sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"" USER_AGENT "\"]}");
1072
1073 if (!stratum_send_line(sctx, s)) {
1074 applog(LOG_ERR, "stratum_subscribe send failed");
1075 goto out;
1076 }
1077
1078 if (!socket_full(sctx->sock, 30)) {
1079 applog(LOG_ERR, "stratum_subscribe timed out");
1080 goto out;
1081 }
1082
1083 sret = stratum_recv_line(sctx);
1084 if (!sret)
1085 goto out;
1086
1087 val = JSON_LOADS(sret, &err);
1088 free(sret);
1089 if (!val) {
1090 applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
1091 goto out;
1092 }
1093
1094 res_val = json_object_get(val, "result");
1095 err_val = json_object_get(val, "error");
1096
1097 if (!res_val || json_is_null(res_val) ||
1098 (err_val && !json_is_null(err_val))) {
1099 if (opt_debug || retry) {
1100 free(s);
1101 if (err_val)
1102 s = json_dumps(err_val, JSON_INDENT(3));
1103 else
1104 s = strdup("(unknown reason)");
1105 applog(LOG_ERR, "JSON-RPC call failed: %s", s);
1106 }
1107 goto out;
1108 }
1109
1110 sid = get_stratum_session_id(res_val);
1111 if (opt_debug && !sid)
1112 applog(LOG_DEBUG, "Failed to get Stratum session id");
1113 xnonce1 = json_string_value(json_array_get(res_val, 1));
1114 if (!xnonce1) {
1115 applog(LOG_ERR, "Failed to get extranonce1");
1116 goto out;
1117 }
1118 xn2_size = json_integer_value(json_array_get(res_val, 2));
1119 if (!xn2_size) {
1120 applog(LOG_ERR, "Failed to get extranonce2_size");
1121 goto out;
1122 }
967738a2 1123 if (xn2_size < 0 || xn2_size > 100) {
1124 applog(LOG_ERR, "Invalid value of extranonce2_size");
1125 goto out;
1126 }
b089cc9f
LJ
1127
1128 pthread_mutex_lock(&sctx->work_lock);
1129 free(sctx->session_id);
1130 free(sctx->xnonce1);
1131 sctx->session_id = sid ? strdup(sid) : NULL;
1132 sctx->xnonce1_size = strlen(xnonce1) / 2;
588f5d90 1133 sctx->xnonce1 = (uchar*) malloc(sctx->xnonce1_size);
b089cc9f
LJ
1134 hex2bin(sctx->xnonce1, xnonce1, sctx->xnonce1_size);
1135 sctx->xnonce2_size = xn2_size;
1136 sctx->next_diff = 1.0;
1137 pthread_mutex_unlock(&sctx->work_lock);
1138
1139 if (opt_debug && sid)
1140 applog(LOG_DEBUG, "Stratum session id: %s", sctx->session_id);
1141
1142 ret = true;
1143
1144out:
1145 free(s);
1146 if (val)
1147 json_decref(val);
1148
1149 if (!ret) {
1150 if (sret && !retry) {
1151 retry = true;
1152 goto start;
1153 }
1154 }
1155
1156 return ret;
1157}
1158
1159bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass)
1160{
1161 json_t *val = NULL, *res_val, *err_val;
1162 char *s, *sret;
1163 json_error_t err;
1164 bool ret = false;
1165
52eb8a13 1166 if (jsonrpc_2) {
588f5d90 1167 s = (char*) malloc(300 + strlen(user) + strlen(pass));
52eb8a13 1168 sprintf(s, "{\"method\": \"login\", \"params\": {"
d213fe90
TP
1169 "\"login\": \"%s\", \"pass\": \"%s\", \"agent\": \"%s\"}, \"id\": 1}",
1170 user, pass, USER_AGENT);
5e287fa4 1171 } else {
588f5d90 1172 s = (char*) malloc(80 + strlen(user) + strlen(pass));
52eb8a13
TP
1173 sprintf(s, "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}",
1174 user, pass);
5e287fa4 1175 }
b089cc9f
LJ
1176
1177 if (!stratum_send_line(sctx, s))
1178 goto out;
1179
1180 while (1) {
1181 sret = stratum_recv_line(sctx);
1182 if (!sret)
1183 goto out;
1184 if (!stratum_handle_method(sctx, sret))
1185 break;
1186 free(sret);
1187 }
1188
1189 val = JSON_LOADS(sret, &err);
1190 free(sret);
1191 if (!val) {
1192 applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
1193 goto out;
1194 }
1195
1196 res_val = json_object_get(val, "result");
1197 err_val = json_object_get(val, "error");
1198
1199 if (!res_val || json_is_false(res_val) ||
1200 (err_val && !json_is_null(err_val))) {
1201 applog(LOG_ERR, "Stratum authentication failed");
1202 goto out;
1203 }
1204
52eb8a13
TP
1205 if (jsonrpc_2) {
1206 rpc2_login_decode(val);
1207 json_t *job_val = json_object_get(res_val, "job");
1208 pthread_mutex_lock(&sctx->work_lock);
1209 if(job_val) rpc2_job_decode(job_val, &sctx->work);
1210 pthread_mutex_unlock(&sctx->work_lock);
1211 }
5e287fa4 1212
b089cc9f
LJ
1213 ret = true;
1214
1215out:
1216 free(s);
1217 if (val)
1218 json_decref(val);
1219
1220 return ret;
1221}
1222
5e287fa4 1223static bool stratum_2_job(struct stratum_ctx *sctx, json_t *params)
1224{
52eb8a13
TP
1225 bool ret = false;
1226 pthread_mutex_lock(&sctx->work_lock);
1227 ret = rpc2_job_decode(params, &sctx->work);
1228 pthread_mutex_unlock(&sctx->work_lock);
1229 return ret;
5e287fa4 1230}
1231
b089cc9f
LJ
1232static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
1233{
1234 const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime;
1235 size_t coinb1_size, coinb2_size;
1236 bool clean, ret = false;
1237 int merkle_count, i;
1238 json_t *merkle_arr;
588f5d90 1239 uchar **merkle;
b089cc9f
LJ
1240
1241 job_id = json_string_value(json_array_get(params, 0));
1242 prevhash = json_string_value(json_array_get(params, 1));
1243 coinb1 = json_string_value(json_array_get(params, 2));
1244 coinb2 = json_string_value(json_array_get(params, 3));
1245 merkle_arr = json_array_get(params, 4);
1246 if (!merkle_arr || !json_is_array(merkle_arr))
1247 goto out;
1248 merkle_count = json_array_size(merkle_arr);
1249 version = json_string_value(json_array_get(params, 5));
1250 nbits = json_string_value(json_array_get(params, 6));
1251 ntime = json_string_value(json_array_get(params, 7));
1252 clean = json_is_true(json_array_get(params, 8));
1253
1254 if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime ||
1255 strlen(prevhash) != 64 || strlen(version) != 8 ||
1256 strlen(nbits) != 8 || strlen(ntime) != 8) {
1257 applog(LOG_ERR, "Stratum notify: invalid parameters");
1258 goto out;
1259 }
588f5d90 1260 merkle = (uchar**) malloc(merkle_count * sizeof(char *));
b089cc9f
LJ
1261 for (i = 0; i < merkle_count; i++) {
1262 const char *s = json_string_value(json_array_get(merkle_arr, i));
1263 if (!s || strlen(s) != 64) {
1264 while (i--)
1265 free(merkle[i]);
1266 free(merkle);
1267 applog(LOG_ERR, "Stratum notify: invalid Merkle branch");
1268 goto out;
1269 }
588f5d90 1270 merkle[i] = (uchar*) malloc(32);
b089cc9f
LJ
1271 hex2bin(merkle[i], s, 32);
1272 }
1273
1274 pthread_mutex_lock(&sctx->work_lock);
1275
1276 coinb1_size = strlen(coinb1) / 2;
1277 coinb2_size = strlen(coinb2) / 2;
1278 sctx->job.coinbase_size = coinb1_size + sctx->xnonce1_size +
1279 sctx->xnonce2_size + coinb2_size;
588f5d90 1280 sctx->job.coinbase = (uchar*) realloc(sctx->job.coinbase, sctx->job.coinbase_size);
b089cc9f
LJ
1281 sctx->job.xnonce2 = sctx->job.coinbase + coinb1_size + sctx->xnonce1_size;
1282 hex2bin(sctx->job.coinbase, coinb1, coinb1_size);
1283 memcpy(sctx->job.coinbase + coinb1_size, sctx->xnonce1, sctx->xnonce1_size);
1284 if (!sctx->job.job_id || strcmp(sctx->job.job_id, job_id))
1285 memset(sctx->job.xnonce2, 0, sctx->xnonce2_size);
1286 hex2bin(sctx->job.xnonce2 + sctx->xnonce2_size, coinb2, coinb2_size);
1287
1288 free(sctx->job.job_id);
1289 sctx->job.job_id = strdup(job_id);
1290 hex2bin(sctx->job.prevhash, prevhash, 32);
1291
1292 for (i = 0; i < sctx->job.merkle_count; i++)
1293 free(sctx->job.merkle[i]);
1294 free(sctx->job.merkle);
1295 sctx->job.merkle = merkle;
1296 sctx->job.merkle_count = merkle_count;
1297
1298 hex2bin(sctx->job.version, version, 4);
1299 hex2bin(sctx->job.nbits, nbits, 4);
1300 hex2bin(sctx->job.ntime, ntime, 4);
1301 sctx->job.clean = clean;
1302
1303 sctx->job.diff = sctx->next_diff;
1304
1305 pthread_mutex_unlock(&sctx->work_lock);
1306
1307 ret = true;
1308
1309out:
1310 return ret;
1311}
1312
1313static bool stratum_set_difficulty(struct stratum_ctx *sctx, json_t *params)
1314{
1315 double diff;
1316
1317 diff = json_number_value(json_array_get(params, 0));
1318 if (diff == 0)
1319 return false;
1320
1321 pthread_mutex_lock(&sctx->work_lock);
1322 sctx->next_diff = diff;
1323 pthread_mutex_unlock(&sctx->work_lock);
1324
070ff29d 1325 applog(LOG_WARNING, "Stratum difficulty set to %g", diff);
b089cc9f
LJ
1326
1327 return true;
1328}
1329
1330static bool stratum_reconnect(struct stratum_ctx *sctx, json_t *params)
1331{
1332 json_t *port_val;
1333 char *url;
1334 const char *host;
1335 int port;
1336
1337 host = json_string_value(json_array_get(params, 0));
1338 port_val = json_array_get(params, 1);
1339 if (json_is_string(port_val))
1340 port = atoi(json_string_value(port_val));
1341 else
1342 port = json_integer_value(port_val);
1343 if (!host || !port)
1344 return false;
1345
588f5d90 1346 url = (char*) malloc(32 + strlen(host));
b089cc9f
LJ
1347 sprintf(url, "stratum+tcp://%s:%d", host, port);
1348
1349 if (!opt_redirect) {
1350 applog(LOG_INFO, "Ignoring request to reconnect to %s", url);
1351 free(url);
1352 return true;
1353 }
1354
1355 applog(LOG_NOTICE, "Server requested reconnection to %s", url);
1356
1357 free(sctx->url);
1358 sctx->url = url;
1359 stratum_disconnect(sctx);
1360
1361 return true;
1362}
1363
1364static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
1365{
1366 char *s;
1367 json_t *val;
1368 bool ret;
1369
1370 if (!id || json_is_null(id))
1371 return false;
1372
1373 val = json_object();
1374 json_object_set(val, "id", id);
1375 json_object_set_new(val, "error", json_null());
1376 json_object_set_new(val, "result", json_string(USER_AGENT));
1377 s = json_dumps(val, 0);
1378 ret = stratum_send_line(sctx, s);
1379 json_decref(val);
1380 free(s);
1381
1382 return ret;
1383}
1384
1385static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *params)
1386{
1387 char *s;
1388 json_t *val;
1389 bool ret;
1390
1391 val = json_array_get(params, 0);
1392 if (val)
1393 applog(LOG_NOTICE, "MESSAGE FROM SERVER: %s", json_string_value(val));
1394
1395 if (!id || json_is_null(id))
1396 return true;
1397
1398 val = json_object();
1399 json_object_set(val, "id", id);
1400 json_object_set_new(val, "error", json_null());
1401 json_object_set_new(val, "result", json_true());
1402 s = json_dumps(val, 0);
1403 ret = stratum_send_line(sctx, s);
1404 json_decref(val);
1405 free(s);
1406
1407 return ret;
1408}
1409
1410bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
1411{
1412 json_t *val, *id, *params;
1413 json_error_t err;
1414 const char *method;
1415 bool ret = false;
1416
1417 val = JSON_LOADS(s, &err);
1418 if (!val) {
1419 applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
1420 goto out;
1421 }
1422
1423 method = json_string_value(json_object_get(val, "method"));
1424 if (!method)
1425 goto out;
1426 id = json_object_get(val, "id");
1427 params = json_object_get(val, "params");
1428
52eb8a13
TP
1429 if (jsonrpc_2) {
1430 if (!strcasecmp(method, "job")) {
1431 ret = stratum_2_job(sctx, params);
1432 goto out;
1433 }
1434 } else {
1435 if (!strcasecmp(method, "mining.notify")) {
1436 ret = stratum_notify(sctx, params);
1437 goto out;
1438 }
1439 if (!strcasecmp(method, "mining.set_difficulty")) {
1440 ret = stratum_set_difficulty(sctx, params);
1441 goto out;
1442 }
1443 if (!strcasecmp(method, "client.reconnect")) {
1444 ret = stratum_reconnect(sctx, params);
1445 goto out;
1446 }
1447 if (!strcasecmp(method, "client.get_version")) {
1448 ret = stratum_get_version(sctx, id);
1449 goto out;
1450 }
1451 if (!strcasecmp(method, "client.show_message")) {
1452 ret = stratum_show_message(sctx, id, params);
1453 goto out;
1454 }
1455 }
b089cc9f
LJ
1456
1457out:
1458 if (val)
1459 json_decref(val);
1460
1461 return ret;
1462}
1463
1464struct thread_q *tq_new(void)
1465{
1466 struct thread_q *tq;
1467
588f5d90 1468 tq = (struct thread_q*) calloc(1, sizeof(*tq));
b089cc9f
LJ
1469 if (!tq)
1470 return NULL;
1471
1472 INIT_LIST_HEAD(&tq->q);
1473 pthread_mutex_init(&tq->mutex, NULL);
1474 pthread_cond_init(&tq->cond, NULL);
1475
1476 return tq;
1477}
1478
1479void tq_free(struct thread_q *tq)
1480{
1481 struct tq_ent *ent, *iter;
1482
1483 if (!tq)
1484 return;
1485
8fb8959f 1486 list_for_each_entry_safe(ent, iter, &tq->q, q_node, struct tq_ent) {
b089cc9f
LJ
1487 list_del(&ent->q_node);
1488 free(ent);
1489 }
1490
1491 pthread_cond_destroy(&tq->cond);
1492 pthread_mutex_destroy(&tq->mutex);
1493
1494 memset(tq, 0, sizeof(*tq)); /* poison */
1495 free(tq);
1496}
1497
1498static void tq_freezethaw(struct thread_q *tq, bool frozen)
1499{
1500 pthread_mutex_lock(&tq->mutex);
1501
1502 tq->frozen = frozen;
1503
1504 pthread_cond_signal(&tq->cond);
1505 pthread_mutex_unlock(&tq->mutex);
1506}
1507
1508void tq_freeze(struct thread_q *tq)
1509{
1510 tq_freezethaw(tq, true);
1511}
1512
1513void tq_thaw(struct thread_q *tq)
1514{
1515 tq_freezethaw(tq, false);
1516}
1517
1518bool tq_push(struct thread_q *tq, void *data)
1519{
1520 struct tq_ent *ent;
1521 bool rc = true;
1522
588f5d90 1523 ent = (struct tq_ent*) calloc(1, sizeof(*ent));
b089cc9f
LJ
1524 if (!ent)
1525 return false;
1526
1527 ent->data = data;
1528 INIT_LIST_HEAD(&ent->q_node);
1529
1530 pthread_mutex_lock(&tq->mutex);
1531
1532 if (!tq->frozen) {
1533 list_add_tail(&ent->q_node, &tq->q);
1534 } else {
1535 free(ent);
1536 rc = false;
1537 }
1538
1539 pthread_cond_signal(&tq->cond);
1540 pthread_mutex_unlock(&tq->mutex);
1541
1542 return rc;
1543}
1544
1545void *tq_pop(struct thread_q *tq, const struct timespec *abstime)
1546{
1547 struct tq_ent *ent;
1548 void *rval = NULL;
1549 int rc;
1550
1551 pthread_mutex_lock(&tq->mutex);
1552
1553 if (!list_empty(&tq->q))
1554 goto pop;
1555
1556 if (abstime)
1557 rc = pthread_cond_timedwait(&tq->cond, &tq->mutex, abstime);
1558 else
1559 rc = pthread_cond_wait(&tq->cond, &tq->mutex);
1560 if (rc)
1561 goto out;
1562 if (list_empty(&tq->q))
1563 goto out;
1564
1565pop:
1566 ent = list_entry(tq->q.next, struct tq_ent, q_node);
1567 rval = ent->data;
1568
1569 list_del(&ent->q_node);
1570 free(ent);
1571
1572out:
1573 pthread_mutex_unlock(&tq->mutex);
1574 return rval;
1575}
f4ccad0e 1576
112f76b2
TP
1577/* sprintf can be used in applog */
1578static char* format_hash(char* buf, uint8_t *hash)
f4ccad0e 1579{
112f76b2
TP
1580 int len = 0;
1581 for (int i=0; i < 32; i += 4) {
1582 len += sprintf(buf+len, "%02x%02x%02x%02x ",
1583 hash[i], hash[i+1], hash[i+2], hash[i+3]);
f4ccad0e 1584 }
112f76b2 1585 return buf;
f4ccad0e
TP
1586}
1587
112f76b2
TP
1588void applog_hash(void *hash)
1589{
1590 char s[128] = {'\0'};
588f5d90 1591 applog(LOG_DEBUG, "%s", format_hash(s, (uchar*) hash));
112f76b2
TP
1592}
1593
1594#define printpfx(n,h) \
1595 printf("%s%12s%s: %s\n", CL_BLU, n, CL_N, format_hash(s, (uint8_t*) h))
1596
f4ccad0e
TP
1597void print_hash_tests(void)
1598{
112f76b2 1599 char* buf[128], hash[128], s[80];
f4ccad0e 1600 memset(buf, 0, sizeof buf);
112f76b2
TP
1601
1602 printf("\n" CL_WHT "CPU HASH ON EMPTY BUFFER RESULTS:" CL_N " (dev purpose)\n\n");
1603
1604 memset(hash, 0, sizeof hash);
1605 sha256d((uint8_t*) &hash[0], (uint8_t*)&buf[0], 64);
1606 printpfx("SHA 256D", hash);
1607
1608 memset(hash, 0, sizeof hash);
1609 heavyhash((uint8_t*) &hash[0], (uint8_t*) &buf[0], 32);
1610 printpfx("Heavy", hash);
1611
1612 memset(hash, 0, sizeof hash);
1613 keccakhash(&hash[0], &buf[0]);
1614 printpfx("Keccak", hash);
1615
15f243e7 1616 memset(hash, 0, sizeof hash);
588f5d90 1617 neoscrypt((uchar*) &hash[0], (uchar*)&buf[0], 80000620);
15f243e7
TP
1618 printpfx("Neoscrypt", hash);
1619
112f76b2
TP
1620 memset(hash, 0, sizeof hash);
1621 quarkhash(&hash[0], &buf[0]);
1622 printpfx("Quark", hash);
1623
1624 memset(hash, 0, sizeof hash);
1625 skeinhash(&hash[0], &buf[0]);
1626 printpfx("Skein", hash);
1627
1628 memset(hash, 0, sizeof hash);
1629 blakehash(&hash[0], &buf[0]);
1630 printpfx("Blake", hash);
1631
df27be47
TP
1632 memset(hash, 0, sizeof hash);
1633 pentablakehash(&hash[0], &buf[0]);
1634 printpfx("Pentablake", hash);
1635
112f76b2
TP
1636 memset(hash, 0, sizeof hash);
1637 inkhash(&hash[0], &buf[0]);
1638 printpfx("Shavite", hash);
f4ccad0e 1639
45792c1b
TP
1640 memset(hash, 0, sizeof hash);
1641 freshhash(&hash[0], &buf[0], 80);
112f76b2 1642 printpfx("Fresh", hash);
45792c1b 1643
98a5c874
TP
1644 memset(hash, 0, sizeof hash);
1645 s3hash(&hash[0], &buf[0]);
1646 printpfx("S3", hash);
1647
f4ccad0e
TP
1648 memset(hash, 0, sizeof hash);
1649 x11hash(&hash[0], &buf[0]);
112f76b2 1650 printpfx("X11", hash);
f4ccad0e
TP
1651
1652 memset(hash, 0, sizeof hash);
1653 x13hash(&hash[0], &buf[0]);
112f76b2 1654 printpfx("X13", hash);
f4ccad0e
TP
1655
1656 memset(hash, 0, sizeof hash);
1657 x14hash(&hash[0], &buf[0]);
112f76b2 1658 printpfx("X14", hash);
f4ccad0e
TP
1659
1660 memset(hash, 0, sizeof hash);
1661 x15hash(&hash[0], &buf[0]);
112f76b2
TP
1662 printpfx("X15", hash);
1663
112f76b2
TP
1664 memset(hash, 0, sizeof hash);
1665 cryptonight_hash(&hash[0], &buf[0], 76);
1666 printpfx("Cryptonight", hash);
f4ccad0e
TP
1667
1668 printf("\n");
1669}
1670
This page took 0.216634 seconds and 4 git commands to generate.