Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/util.c
1201 views
1
/*
2
* Copyright 2010 Jeff Garzik
3
* Copyright 2012 Luke Dashjr
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>
22
#include <limits.h>
23
#include <errno.h>
24
#include <unistd.h>
25
#include <jansson.h>
26
#include <curl/curl.h>
27
#include <time.h>
28
#include <sys/stat.h>
29
#if defined(WIN32)
30
#include <winsock2.h>
31
#include <mstcpip.h>
32
#include "compat/winansi.h"
33
#else
34
#include <sys/socket.h>
35
#include <netinet/in.h>
36
#include <netinet/tcp.h>
37
#endif
38
39
#ifndef _MSC_VER
40
/* dirname() linux/mingw, else in compat.h */
41
#include <libgen.h>
42
#endif
43
44
#include "miner.h"
45
#include "elist.h"
46
47
extern pthread_mutex_t stats_lock;
48
49
struct data_buffer {
50
void *buf;
51
size_t len;
52
};
53
54
struct upload_buffer {
55
const void *buf;
56
size_t len;
57
size_t pos;
58
};
59
60
struct header_info {
61
char *lp_path;
62
char *reason;
63
char *stratum_url;
64
};
65
66
struct tq_ent {
67
void *data;
68
struct list_head q_node;
69
};
70
71
struct thread_q {
72
struct list_head q;
73
74
bool frozen;
75
76
pthread_mutex_t mutex;
77
pthread_cond_t cond;
78
};
79
80
void applog(int prio, const char *fmt, ...)
81
{
82
va_list ap;
83
84
va_start(ap, fmt);
85
86
#ifdef HAVE_SYSLOG_H
87
if (use_syslog) {
88
va_list ap2;
89
char *buf;
90
int len;
91
92
/* custom colors to syslog prio */
93
if (prio > LOG_DEBUG) {
94
switch (prio) {
95
case LOG_BLUE: prio = LOG_NOTICE; break;
96
}
97
}
98
99
va_copy(ap2, ap);
100
len = vsnprintf(NULL, 0, fmt, ap2) + 1;
101
va_end(ap2);
102
buf = alloca(len);
103
if (vsnprintf(buf, len, fmt, ap) >= 0)
104
syslog(prio, "%s", buf);
105
}
106
#else
107
if (0) {}
108
#endif
109
else {
110
const char* color = "";
111
char *f;
112
int len;
113
struct tm tm;
114
time_t now = time(NULL);
115
116
localtime_r(&now, &tm);
117
118
switch (prio) {
119
case LOG_ERR: color = CL_RED; break;
120
case LOG_WARNING: color = CL_YLW; break;
121
case LOG_NOTICE: color = CL_WHT; break;
122
case LOG_INFO: color = ""; break;
123
case LOG_DEBUG: color = CL_GRY; break;
124
125
case LOG_BLUE:
126
prio = LOG_NOTICE;
127
color = CL_CYN;
128
break;
129
}
130
if (!use_colors)
131
color = "";
132
133
len = 64 + (int) strlen(fmt) + 2;
134
f = (char*) malloc(len);
135
sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
136
tm.tm_year + 1900,
137
tm.tm_mon + 1,
138
tm.tm_mday,
139
tm.tm_hour,
140
tm.tm_min,
141
tm.tm_sec,
142
color,
143
fmt,
144
use_colors ? CL_N : ""
145
);
146
pthread_mutex_lock(&applog_lock);
147
vfprintf(stdout, f, ap); /* atomic write to stdout */
148
fflush(stdout);
149
free(f);
150
pthread_mutex_unlock(&applog_lock);
151
}
152
va_end(ap);
153
}
154
155
/* Get default config.json path (will be system specific) */
156
void get_defconfig_path(char *out, size_t bufsize, char *argv0)
157
{
158
char *cmd = strdup(argv0);
159
char *dir = dirname(cmd);
160
const char *sep = strstr(dir, "\\") ? "\\" : "/";
161
struct stat info = { 0 };
162
#ifdef WIN32
163
snprintf(out, bufsize, "%s\\cpuminer\\cpuminer-conf.json", getenv("APPDATA"));
164
#else
165
snprintf(out, bufsize, "%s\\.cpuminer\\cpuminer-conf.json", getenv("HOME"));
166
#endif
167
if (dir && stat(out, &info) != 0) {
168
snprintf(out, bufsize, "%s%scpuminer-conf.json", dir, sep);
169
}
170
if (stat(out, &info) != 0) {
171
out[0] = '\0';
172
return;
173
}
174
out[bufsize - 1] = '\0';
175
free(cmd);
176
}
177
178
179
void format_hashrate(double hashrate, char *output)
180
{
181
char prefix = '\0';
182
183
if (hashrate < 10000) {
184
// nop
185
}
186
else if (hashrate < 1e7) {
187
prefix = 'k';
188
hashrate *= 1e-3;
189
}
190
else if (hashrate < 1e10) {
191
prefix = 'M';
192
hashrate *= 1e-6;
193
}
194
else if (hashrate < 1e13) {
195
prefix = 'G';
196
hashrate *= 1e-9;
197
}
198
else {
199
prefix = 'T';
200
hashrate *= 1e-12;
201
}
202
203
sprintf(
204
output,
205
prefix ? "%.2f %cH/s" : "%.2f H/s%c",
206
hashrate, prefix
207
);
208
}
209
210
/* Modify the representation of integer numbers which would cause an overflow
211
* so that they are treated as floating-point numbers.
212
* This is a hack to overcome the limitations of some versions of Jansson. */
213
static char *hack_json_numbers(const char *in)
214
{
215
char *out;
216
int i, off, intoff;
217
bool in_str, in_int;
218
219
out = (char*) calloc(2 * strlen(in) + 1, 1);
220
if (!out)
221
return NULL;
222
off = intoff = 0;
223
in_str = in_int = false;
224
for (i = 0; in[i]; i++) {
225
char c = in[i];
226
if (c == '"') {
227
in_str = !in_str;
228
} else if (c == '\\') {
229
out[off++] = c;
230
if (!in[++i])
231
break;
232
} else if (!in_str && !in_int && isdigit(c)) {
233
intoff = off;
234
in_int = true;
235
} else if (in_int && !isdigit(c)) {
236
if (c != '.' && c != 'e' && c != 'E' && c != '+' && c != '-') {
237
in_int = false;
238
if (off - intoff > 4) {
239
char *end;
240
#if JSON_INTEGER_IS_LONG_LONG
241
errno = 0;
242
strtoll(out + intoff, &end, 10);
243
if (!*end && errno == ERANGE) {
244
#else
245
long l;
246
errno = 0;
247
l = strtol(out + intoff, &end, 10);
248
if (!*end && (errno == ERANGE || l > INT_MAX)) {
249
#endif
250
out[off++] = '.';
251
out[off++] = '0';
252
}
253
}
254
}
255
}
256
out[off++] = in[i];
257
}
258
return out;
259
}
260
261
static void databuf_free(struct data_buffer *db)
262
{
263
if (!db)
264
return;
265
266
free(db->buf);
267
268
memset(db, 0, sizeof(*db));
269
}
270
271
static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
272
void *user_data)
273
{
274
struct data_buffer *db = (struct data_buffer *) user_data;
275
size_t len = size * nmemb;
276
size_t oldlen, newlen;
277
void *newmem;
278
static const unsigned char zero = 0;
279
280
oldlen = db->len;
281
newlen = oldlen + len;
282
283
newmem = realloc(db->buf, newlen + 1);
284
if (!newmem)
285
return 0;
286
287
db->buf = newmem;
288
db->len = newlen;
289
memcpy((uchar*) db->buf + oldlen, ptr, len);
290
memcpy((uchar*) db->buf + newlen, &zero, 1); /* null terminate */
291
292
return len;
293
}
294
295
static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
296
void *user_data)
297
{
298
struct upload_buffer *ub = (struct upload_buffer *) user_data;
299
size_t len = size * nmemb;
300
301
if (len > ub->len - ub->pos)
302
len = ub->len - ub->pos;
303
304
if (len) {
305
memcpy(ptr, ((uchar*)ub->buf) + ub->pos, len);
306
ub->pos += len;
307
}
308
309
return len;
310
}
311
312
#if LIBCURL_VERSION_NUM >= 0x071200
313
static int seek_data_cb(void *user_data, curl_off_t offset, int origin)
314
{
315
struct upload_buffer *ub = (struct upload_buffer *) user_data;
316
317
switch (origin) {
318
case SEEK_SET:
319
ub->pos = (size_t) offset;
320
break;
321
case SEEK_CUR:
322
ub->pos += (size_t) offset;
323
break;
324
case SEEK_END:
325
ub->pos = ub->len + (size_t) offset;
326
break;
327
default:
328
return 1; /* CURL_SEEKFUNC_FAIL */
329
}
330
331
return 0; /* CURL_SEEKFUNC_OK */
332
}
333
#endif
334
335
static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
336
{
337
struct header_info *hi = (struct header_info *) user_data;
338
size_t remlen, slen, ptrlen = size * nmemb;
339
char *rem, *val = NULL, *key = NULL;
340
void *tmp;
341
342
val = (char*) calloc(1, ptrlen);
343
key = (char*) calloc(1, ptrlen);
344
if (!key || !val)
345
goto out;
346
347
tmp = memchr(ptr, ':', ptrlen);
348
if (!tmp || (tmp == ptr)) /* skip empty keys / blanks */
349
goto out;
350
slen = (char*)tmp - (char*)ptr;
351
if ((slen + 1) == ptrlen) /* skip key w/ no value */
352
goto out;
353
memcpy(key, ptr, slen); /* store & nul term key */
354
key[slen] = 0;
355
356
rem = (char*)ptr + slen + 1; /* trim value's leading whitespace */
357
remlen = ptrlen - slen - 1;
358
while ((remlen > 0) && (isspace(*rem))) {
359
remlen--;
360
rem++;
361
}
362
363
memcpy(val, rem, remlen); /* store value, trim trailing ws */
364
val[remlen] = 0;
365
while ((*val) && (isspace(val[strlen(val) - 1]))) {
366
val[strlen(val) - 1] = 0;
367
}
368
369
if (!strcasecmp("X-Long-Polling", key)) {
370
hi->lp_path = val; /* steal memory reference */
371
val = NULL;
372
}
373
374
if (!strcasecmp("X-Reject-Reason", key)) {
375
hi->reason = val; /* steal memory reference */
376
val = NULL;
377
}
378
379
if (!strcasecmp("X-Stratum", key)) {
380
hi->stratum_url = val; /* steal memory reference */
381
val = NULL;
382
}
383
384
out:
385
free(key);
386
free(val);
387
return ptrlen;
388
}
389
390
#if LIBCURL_VERSION_NUM >= 0x070f06
391
static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd,
392
curlsocktype purpose)
393
{
394
#ifdef __linux
395
int tcp_keepcnt = 3;
396
#endif
397
int tcp_keepintvl = 50;
398
int tcp_keepidle = 50;
399
#ifndef WIN32
400
int keepalive = 1;
401
if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive,
402
sizeof(keepalive))))
403
return 1;
404
#ifdef __linux
405
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT,
406
&tcp_keepcnt, sizeof(tcp_keepcnt))))
407
return 1;
408
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE,
409
&tcp_keepidle, sizeof(tcp_keepidle))))
410
return 1;
411
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL,
412
&tcp_keepintvl, sizeof(tcp_keepintvl))))
413
return 1;
414
#endif /* __linux */
415
#ifdef __APPLE_CC__
416
if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
417
&tcp_keepintvl, sizeof(tcp_keepintvl))))
418
return 1;
419
#endif /* __APPLE_CC__ */
420
#else /* WIN32 */
421
struct tcp_keepalive vals;
422
vals.onoff = 1;
423
vals.keepalivetime = tcp_keepidle * 1000;
424
vals.keepaliveinterval = tcp_keepintvl * 1000;
425
DWORD outputBytes;
426
if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals),
427
NULL, 0, &outputBytes, NULL, NULL)))
428
return 1;
429
#endif /* WIN32 */
430
431
return 0;
432
}
433
#endif
434
435
json_t *json_rpc_call(CURL *curl, const char *url,
436
const char *userpass, const char *rpc_req,
437
int *curl_err, int flags)
438
{
439
json_t *val, *err_val, *res_val;
440
int rc;
441
long http_rc;
442
struct data_buffer all_data = {0};
443
struct upload_buffer upload_data;
444
char *json_buf;
445
json_error_t err;
446
struct curl_slist *headers = NULL;
447
char len_hdr[64];
448
char curl_err_str[CURL_ERROR_SIZE] = { 0 };
449
long timeout = (flags & JSON_RPC_LONGPOLL) ? opt_timeout : 30;
450
struct header_info hi = {0};
451
452
/* it is assumed that 'curl' is freshly [re]initialized at this pt */
453
454
if (opt_protocol)
455
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
456
curl_easy_setopt(curl, CURLOPT_URL, url);
457
if (opt_cert)
458
curl_easy_setopt(curl, CURLOPT_CAINFO, opt_cert);
459
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
460
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
461
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 0);
462
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
463
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
464
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
465
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
466
curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
467
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
468
#if LIBCURL_VERSION_NUM >= 0x071200
469
curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, &seek_data_cb);
470
curl_easy_setopt(curl, CURLOPT_SEEKDATA, &upload_data);
471
#endif
472
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
473
if (opt_redirect)
474
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
475
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
476
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
477
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
478
if (opt_proxy) {
479
curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy);
480
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type);
481
}
482
if (userpass) {
483
curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
484
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
485
}
486
#if LIBCURL_VERSION_NUM >= 0x070f06
487
if (flags & JSON_RPC_LONGPOLL)
488
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
489
#endif
490
curl_easy_setopt(curl, CURLOPT_POST, 1);
491
492
if (opt_protocol)
493
applog(LOG_DEBUG, "JSON protocol request:\n%s\n", rpc_req);
494
495
upload_data.buf = rpc_req;
496
upload_data.len = strlen(rpc_req);
497
upload_data.pos = 0;
498
sprintf(len_hdr, "Content-Length: %lu",
499
(unsigned long) upload_data.len);
500
501
headers = curl_slist_append(headers, "Content-Type: application/json");
502
headers = curl_slist_append(headers, len_hdr);
503
headers = curl_slist_append(headers, "User-Agent: " USER_AGENT);
504
headers = curl_slist_append(headers, "X-Mining-Extensions: longpoll reject-reason");
505
//headers = curl_slist_append(headers, "Accept:"); /* disable Accept hdr*/
506
//headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
507
508
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
509
510
rc = curl_easy_perform(curl);
511
if (curl_err != NULL)
512
*curl_err = rc;
513
if (rc) {
514
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_rc);
515
if (!((flags & JSON_RPC_LONGPOLL) && rc == CURLE_OPERATION_TIMEDOUT) &&
516
!((flags & JSON_RPC_QUIET_404) && http_rc == 404))
517
applog(LOG_ERR, "HTTP request failed: %s", curl_err_str);
518
if (curl_err && (flags & JSON_RPC_QUIET_404) && http_rc == 404)
519
*curl_err = CURLE_OK;
520
goto err_out;
521
}
522
523
/* If X-Stratum was found, activate Stratum */
524
if (want_stratum && hi.stratum_url &&
525
!strncasecmp(hi.stratum_url, "stratum+tcp://", 14)) {
526
have_stratum = true;
527
tq_push(thr_info[stratum_thr_id].q, hi.stratum_url);
528
hi.stratum_url = NULL;
529
}
530
531
/* If X-Long-Polling was found, activate long polling */
532
if (!have_longpoll && want_longpoll && hi.lp_path && !have_gbt &&
533
allow_getwork && !have_stratum) {
534
have_longpoll = true;
535
tq_push(thr_info[longpoll_thr_id].q, hi.lp_path);
536
hi.lp_path = NULL;
537
}
538
539
if (!all_data.buf) {
540
applog(LOG_ERR, "Empty data received in json_rpc_call.");
541
goto err_out;
542
}
543
544
json_buf = hack_json_numbers((char*) all_data.buf);
545
errno = 0; /* needed for Jansson < 2.1 */
546
val = JSON_LOADS(json_buf, &err);
547
free(json_buf);
548
if (!val) {
549
applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
550
goto err_out;
551
}
552
553
if (opt_protocol) {
554
char *s = json_dumps(val, JSON_INDENT(3));
555
applog(LOG_DEBUG, "JSON protocol response:\n%s", s);
556
free(s);
557
}
558
559
/* JSON-RPC valid response returns a 'result' and a null 'error'. */
560
res_val = json_object_get(val, "result");
561
err_val = json_object_get(val, "error");
562
563
if (!res_val || (err_val && !json_is_null(err_val)
564
&& !(flags & JSON_RPC_IGNOREERR))) {
565
566
char *s = NULL;
567
568
if (err_val) {
569
s = json_dumps(err_val, 0);
570
json_t *msg = json_object_get(err_val, "message");
571
json_t *err_code = json_object_get(err_val, "code");
572
if (curl_err && json_integer_value(err_code))
573
*curl_err = (int)json_integer_value(err_code);
574
575
if (msg && json_is_string(msg)) {
576
free(s);
577
s = strdup(json_string_value(msg));
578
if (have_longpoll && s && !strcmp(s, "method not getwork")) {
579
json_decref(err_val);
580
free(s);
581
goto err_out;
582
}
583
}
584
json_decref(err_val);
585
}
586
else
587
s = strdup("(unknown reason)");
588
589
if (!curl_err || opt_debug)
590
applog(LOG_ERR, "JSON-RPC call failed: %s", s);
591
592
free(s);
593
594
goto err_out;
595
}
596
597
if (hi.reason)
598
json_object_set_new(val, "reject-reason", json_string(hi.reason));
599
600
databuf_free(&all_data);
601
curl_slist_free_all(headers);
602
curl_easy_reset(curl);
603
return val;
604
605
err_out:
606
free(hi.lp_path);
607
free(hi.reason);
608
free(hi.stratum_url);
609
databuf_free(&all_data);
610
curl_slist_free_all(headers);
611
curl_easy_reset(curl);
612
return NULL;
613
}
614
615
/* used to load a remote config */
616
json_t* json_load_url(char* cfg_url, json_error_t *err)
617
{
618
char err_str[CURL_ERROR_SIZE] = { 0 };
619
struct data_buffer all_data = { 0 };
620
int rc = 0; json_t *cfg = NULL;
621
CURL *curl = curl_easy_init();
622
if (unlikely(!curl)) {
623
applog(LOG_ERR, "Remote config init failed!");
624
return NULL;
625
}
626
curl_easy_setopt(curl, CURLOPT_URL, cfg_url);
627
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
628
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
629
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, err_str);
630
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
631
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
632
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
633
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
634
if (opt_proxy) {
635
curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy);
636
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type);
637
} else if (getenv("http_proxy")) {
638
if (getenv("all_proxy"))
639
curl_easy_setopt(curl, CURLOPT_PROXY, getenv("all_proxy"));
640
else if (getenv("ALL_PROXY"))
641
curl_easy_setopt(curl, CURLOPT_PROXY, getenv("ALL_PROXY"));
642
else
643
curl_easy_setopt(curl, CURLOPT_PROXY, "");
644
}
645
rc = curl_easy_perform(curl);
646
if (rc) {
647
applog(LOG_ERR, "Remote config read failed: %s", err_str);
648
goto err_out;
649
}
650
if (!all_data.buf || !all_data.len) {
651
applog(LOG_ERR, "Empty data received for config");
652
goto err_out;
653
}
654
655
cfg = JSON_LOADS((char*)all_data.buf, err);
656
err_out:
657
curl_easy_cleanup(curl);
658
return cfg;
659
}
660
661
void bin2hex(char *s, const unsigned char *p, size_t len)
662
{
663
for (size_t i = 0; i < len; i++)
664
sprintf(s + (i * 2), "%02x", (unsigned int) p[i]);
665
}
666
667
char *abin2hex(const unsigned char *p, size_t len)
668
{
669
char *s = (char*) malloc((len * 2) + 1);
670
if (!s)
671
return NULL;
672
bin2hex(s, p, len);
673
return s;
674
}
675
676
bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
677
{
678
char hex_byte[3];
679
char *ep;
680
681
hex_byte[2] = '\0';
682
683
while (*hexstr && len) {
684
if (!hexstr[1]) {
685
applog(LOG_ERR, "hex2bin str truncated");
686
return false;
687
}
688
hex_byte[0] = hexstr[0];
689
hex_byte[1] = hexstr[1];
690
*p = (unsigned char) strtol(hex_byte, &ep, 16);
691
if (*ep) {
692
applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte);
693
return false;
694
}
695
p++;
696
hexstr += 2;
697
len--;
698
}
699
700
return(!len) ? true : false;
701
/* return (len == 0 && *hexstr == 0) ? true : false; */
702
}
703
704
int varint_encode(unsigned char *p, uint64_t n)
705
{
706
int i;
707
if (n < 0xfd) {
708
p[0] = (uchar) n;
709
return 1;
710
}
711
if (n <= 0xffff) {
712
p[0] = 0xfd;
713
p[1] = n & 0xff;
714
p[2] = (uchar) (n >> 8);
715
return 3;
716
}
717
if (n <= 0xffffffff) {
718
p[0] = 0xfe;
719
for (i = 1; i < 5; i++) {
720
p[i] = n & 0xff;
721
n >>= 8;
722
}
723
return 5;
724
}
725
p[0] = 0xff;
726
for (i = 1; i < 9; i++) {
727
p[i] = n & 0xff;
728
n >>= 8;
729
}
730
return 9;
731
}
732
733
static const char b58digits[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
734
735
static bool b58dec(unsigned char *bin, size_t binsz, const char *b58)
736
{
737
size_t i, j;
738
uint64_t t;
739
uint32_t c;
740
uint32_t *outi;
741
size_t outisz = (binsz + 3) / 4;
742
int rem = binsz % 4;
743
uint32_t remmask = 0xffffffff << (8 * rem);
744
size_t b58sz = strlen(b58);
745
bool rc = false;
746
747
outi = (uint32_t *) calloc(outisz, sizeof(*outi));
748
749
for (i = 0; i < b58sz; ++i) {
750
for (c = 0; b58digits[c] != b58[i]; c++)
751
if (!b58digits[c])
752
goto out;
753
for (j = outisz; j--; ) {
754
t = (uint64_t)outi[j] * 58 + c;
755
c = t >> 32;
756
outi[j] = t & 0xffffffff;
757
}
758
if (c || outi[0] & remmask)
759
goto out;
760
}
761
762
j = 0;
763
switch (rem) {
764
case 3:
765
*(bin++) = (outi[0] >> 16) & 0xff;
766
case 2:
767
*(bin++) = (outi[0] >> 8) & 0xff;
768
case 1:
769
*(bin++) = outi[0] & 0xff;
770
++j;
771
default:
772
break;
773
}
774
for (; j < outisz; ++j) {
775
be32enc((uint32_t *)bin, outi[j]);
776
bin += sizeof(uint32_t);
777
}
778
779
rc = true;
780
out:
781
free(outi);
782
return rc;
783
}
784
785
static int b58check(unsigned char *bin, size_t binsz, const char *b58)
786
{
787
unsigned char buf[32];
788
int i;
789
790
sha256d(buf, bin, (int) (binsz - 4));
791
if (memcmp(&bin[binsz - 4], buf, 4))
792
return -1;
793
794
/* Check number of zeros is correct AFTER verifying checksum
795
* (to avoid possibility of accessing the string beyond the end) */
796
for (i = 0; bin[i] == '\0' && b58[i] == '1'; ++i);
797
if (bin[i] == '\0' || b58[i] == '1')
798
return -3;
799
800
return bin[0];
801
}
802
803
bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen)
804
{
805
const char *hexstr;
806
json_t *tmp;
807
808
tmp = json_object_get(obj, key);
809
if (unlikely(!tmp)) {
810
applog(LOG_ERR, "JSON key '%s' not found", key);
811
return false;
812
}
813
hexstr = json_string_value(tmp);
814
if (unlikely(!hexstr)) {
815
applog(LOG_ERR, "JSON key '%s' is not a string", key);
816
return false;
817
}
818
if (!hex2bin((uchar*) buf, hexstr, buflen))
819
return false;
820
821
return true;
822
}
823
824
size_t address_to_script(unsigned char *out, size_t outsz, const char *addr)
825
{
826
unsigned char addrbin[25];
827
int addrver;
828
size_t rv;
829
830
if (!b58dec(addrbin, sizeof(addrbin), addr))
831
return 0;
832
addrver = b58check(addrbin, sizeof(addrbin), addr);
833
if (addrver < 0)
834
return 0;
835
switch (addrver) {
836
case 5: /* Bitcoin script hash */
837
case 196: /* Testnet script hash */
838
if (outsz < (rv = 23))
839
return rv;
840
out[ 0] = 0xa9; /* OP_HASH160 */
841
out[ 1] = 0x14; /* push 20 bytes */
842
memcpy(&out[2], &addrbin[1], 20);
843
out[22] = 0x87; /* OP_EQUAL */
844
return rv;
845
default:
846
if (outsz < (rv = 25))
847
return rv;
848
out[ 0] = 0x76; /* OP_DUP */
849
out[ 1] = 0xa9; /* OP_HASH160 */
850
out[ 2] = 0x14; /* push 20 bytes */
851
memcpy(&out[3], &addrbin[1], 20);
852
out[23] = 0x88; /* OP_EQUALVERIFY */
853
out[24] = 0xac; /* OP_CHECKSIG */
854
return rv;
855
}
856
}
857
858
/* Subtract the `struct timeval' values X and Y,
859
storing the result in RESULT.
860
Return 1 if the difference is negative, otherwise 0. */
861
int timeval_subtract(struct timeval *result, struct timeval *x,
862
struct timeval *y)
863
{
864
/* Perform the carry for the later subtraction by updating Y. */
865
if (x->tv_usec < y->tv_usec) {
866
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
867
y->tv_usec -= 1000000 * nsec;
868
y->tv_sec += nsec;
869
}
870
if (x->tv_usec - y->tv_usec > 1000000) {
871
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
872
y->tv_usec += 1000000 * nsec;
873
y->tv_sec -= nsec;
874
}
875
876
/* Compute the time remaining to wait.
877
* `tv_usec' is certainly positive. */
878
result->tv_sec = x->tv_sec - y->tv_sec;
879
result->tv_usec = x->tv_usec - y->tv_usec;
880
881
/* Return 1 if result is negative. */
882
return x->tv_sec < y->tv_sec;
883
}
884
885
bool fulltest(const uint32_t *hash, const uint32_t *target)
886
{
887
int i;
888
bool rc = true;
889
890
for (i = 7; i >= 0; i--) {
891
if (hash[i] > target[i]) {
892
rc = false;
893
break;
894
}
895
if (hash[i] < target[i]) {
896
rc = true;
897
break;
898
}
899
}
900
901
if (opt_debug) {
902
uint32_t hash_be[8], target_be[8];
903
char hash_str[65], target_str[65];
904
905
for (i = 0; i < 8; i++) {
906
be32enc(hash_be + i, hash[7 - i]);
907
be32enc(target_be + i, target[7 - i]);
908
}
909
bin2hex(hash_str, (unsigned char *)hash_be, 32);
910
bin2hex(target_str, (unsigned char *)target_be, 32);
911
912
applog(LOG_DEBUG, "DEBUG: %s\nHash: %s\nTarget: %s",
913
rc ? "hash <= target"
914
: "hash > target (false positive)",
915
hash_str,
916
target_str);
917
}
918
919
return rc;
920
}
921
922
void diff_to_target(uint32_t *target, double diff)
923
{
924
uint64_t m;
925
int k;
926
927
for (k = 6; k > 0 && diff > 1.0; k--)
928
diff /= 4294967296.0;
929
m = (uint64_t)(4294901760.0 / diff);
930
if (m == 0 && k == 6)
931
memset(target, 0xff, 32);
932
else {
933
memset(target, 0, 32);
934
target[k] = (uint32_t)m;
935
target[k + 1] = (uint32_t)(m >> 32);
936
}
937
}
938
939
// Only used by stratum pools
940
void work_set_target(struct work* work, double diff)
941
{
942
diff_to_target(work->target, diff);
943
work->targetdiff = diff;
944
}
945
946
// Only used by longpoll pools
947
double target_to_diff(uint32_t* target)
948
{
949
uchar* tgt = (uchar*) target;
950
uint64_t m =
951
(uint64_t)tgt[29] << 56 |
952
(uint64_t)tgt[28] << 48 |
953
(uint64_t)tgt[27] << 40 |
954
(uint64_t)tgt[26] << 32 |
955
(uint64_t)tgt[25] << 24 |
956
(uint64_t)tgt[24] << 16 |
957
(uint64_t)tgt[23] << 8 |
958
(uint64_t)tgt[22] << 0;
959
960
if (!m)
961
return 0.;
962
else
963
return (double)0x0000ffff00000000/m;
964
}
965
966
#ifdef WIN32
967
#define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK)
968
#else
969
#define socket_blocks() (errno == EAGAIN || errno == EWOULDBLOCK)
970
#endif
971
972
static bool send_line(curl_socket_t sock, char *s)
973
{
974
size_t sent = 0;
975
int len;
976
977
len = (int) strlen(s);
978
s[len++] = '\n';
979
980
while (len > 0) {
981
struct timeval timeout = {0, 0};
982
int n;
983
fd_set wd;
984
985
FD_ZERO(&wd);
986
FD_SET(sock, &wd);
987
if (select((int) (sock + 1), NULL, &wd, NULL, &timeout) < 1)
988
return false;
989
n = send(sock, s + sent, len, 0);
990
if (n < 0) {
991
if (!socket_blocks())
992
return false;
993
n = 0;
994
}
995
sent += n;
996
len -= n;
997
}
998
999
return true;
1000
}
1001
1002
bool stratum_send_line(struct stratum_ctx *sctx, char *s)
1003
{
1004
bool ret = false;
1005
1006
if (opt_protocol)
1007
applog(LOG_DEBUG, "> %s", s);
1008
1009
pthread_mutex_lock(&sctx->sock_lock);
1010
ret = send_line(sctx->sock, s);
1011
pthread_mutex_unlock(&sctx->sock_lock);
1012
1013
return ret;
1014
}
1015
1016
static bool socket_full(curl_socket_t sock, int timeout)
1017
{
1018
struct timeval tv;
1019
fd_set rd;
1020
1021
FD_ZERO(&rd);
1022
FD_SET(sock, &rd);
1023
tv.tv_sec = timeout;
1024
tv.tv_usec = 0;
1025
if (select((int)(sock + 1), &rd, NULL, NULL, &tv) > 0)
1026
return true;
1027
return false;
1028
}
1029
1030
bool stratum_socket_full(struct stratum_ctx *sctx, int timeout)
1031
{
1032
return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout);
1033
}
1034
1035
#define RBUFSIZE 2048
1036
#define RECVSIZE (RBUFSIZE - 4)
1037
1038
static void stratum_buffer_append(struct stratum_ctx *sctx, const char *s)
1039
{
1040
size_t old, n;
1041
1042
old = strlen(sctx->sockbuf);
1043
n = old + strlen(s) + 1;
1044
if (n >= sctx->sockbuf_size) {
1045
sctx->sockbuf_size = n + (RBUFSIZE - (n % RBUFSIZE));
1046
sctx->sockbuf = (char*) realloc(sctx->sockbuf, sctx->sockbuf_size);
1047
}
1048
strcpy(sctx->sockbuf + old, s);
1049
}
1050
1051
char *stratum_recv_line(struct stratum_ctx *sctx)
1052
{
1053
ssize_t len, buflen;
1054
char *tok, *sret = NULL;
1055
1056
if (!strstr(sctx->sockbuf, "\n")) {
1057
bool ret = true;
1058
time_t rstart;
1059
1060
time(&rstart);
1061
if (!socket_full(sctx->sock, 60)) {
1062
applog(LOG_ERR, "stratum_recv_line timed out");
1063
goto out;
1064
}
1065
do {
1066
char s[RBUFSIZE];
1067
ssize_t n;
1068
1069
memset(s, 0, RBUFSIZE);
1070
n = recv(sctx->sock, s, RECVSIZE, 0);
1071
if (!n) {
1072
ret = false;
1073
break;
1074
}
1075
if (n < 0) {
1076
if (!socket_blocks() || !socket_full(sctx->sock, 1)) {
1077
ret = false;
1078
break;
1079
}
1080
} else
1081
stratum_buffer_append(sctx, s);
1082
} while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n"));
1083
1084
if (!ret) {
1085
applog(LOG_ERR, "stratum_recv_line failed");
1086
goto out;
1087
}
1088
}
1089
1090
buflen = (ssize_t) strlen(sctx->sockbuf);
1091
tok = strtok(sctx->sockbuf, "\n");
1092
if (!tok) {
1093
applog(LOG_ERR, "stratum_recv_line failed to parse a newline-terminated string");
1094
goto out;
1095
}
1096
sret = strdup(tok);
1097
len = (ssize_t) strlen(sret);
1098
1099
if (buflen > len + 1)
1100
memmove(sctx->sockbuf, sctx->sockbuf + len + 1, buflen - len + 1);
1101
else
1102
sctx->sockbuf[0] = '\0';
1103
1104
out:
1105
if (sret && opt_protocol)
1106
applog(LOG_DEBUG, "< %s", sret);
1107
return sret;
1108
}
1109
1110
#if LIBCURL_VERSION_NUM >= 0x071101
1111
static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose,
1112
struct curl_sockaddr *addr)
1113
{
1114
curl_socket_t *sock = (curl_socket_t*) clientp;
1115
*sock = socket(addr->family, addr->socktype, addr->protocol);
1116
return *sock;
1117
}
1118
#endif
1119
1120
bool stratum_connect(struct stratum_ctx *sctx, const char *url)
1121
{
1122
CURL *curl;
1123
int rc;
1124
1125
pthread_mutex_lock(&sctx->sock_lock);
1126
if (sctx->curl)
1127
curl_easy_cleanup(sctx->curl);
1128
sctx->curl = curl_easy_init();
1129
if (!sctx->curl) {
1130
applog(LOG_ERR, "CURL initialization failed");
1131
pthread_mutex_unlock(&sctx->sock_lock);
1132
return false;
1133
}
1134
curl = sctx->curl;
1135
if (!sctx->sockbuf) {
1136
sctx->sockbuf = (char*) calloc(RBUFSIZE, 1);
1137
sctx->sockbuf_size = RBUFSIZE;
1138
}
1139
sctx->sockbuf[0] = '\0';
1140
pthread_mutex_unlock(&sctx->sock_lock);
1141
1142
if (url != sctx->url) {
1143
free(sctx->url);
1144
sctx->url = strdup(url);
1145
}
1146
free(sctx->curl_url);
1147
sctx->curl_url = (char*) malloc(strlen(url));
1148
sprintf(sctx->curl_url, "http%s", strstr(url, "://"));
1149
1150
if (opt_protocol)
1151
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
1152
curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url);
1153
curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
1154
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
1155
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str);
1156
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
1157
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
1158
if (opt_proxy) {
1159
curl_easy_setopt(curl, CURLOPT_PROXY, opt_proxy);
1160
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, opt_proxy_type);
1161
}
1162
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1);
1163
#if LIBCURL_VERSION_NUM >= 0x070f06
1164
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb);
1165
#endif
1166
#if LIBCURL_VERSION_NUM >= 0x071101
1167
curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb);
1168
curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock);
1169
#endif
1170
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
1171
1172
rc = curl_easy_perform(curl);
1173
if (rc) {
1174
applog(LOG_ERR, "Stratum connection failed: %s", sctx->curl_err_str);
1175
curl_easy_cleanup(curl);
1176
sctx->curl = NULL;
1177
return false;
1178
}
1179
1180
#if LIBCURL_VERSION_NUM < 0x071101
1181
/* CURLINFO_LASTSOCKET is broken on Win64; only use it as a last resort */
1182
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sctx->sock);
1183
#endif
1184
1185
return true;
1186
}
1187
1188
void stratum_disconnect(struct stratum_ctx *sctx)
1189
{
1190
pthread_mutex_lock(&sctx->sock_lock);
1191
if (sctx->curl) {
1192
curl_easy_cleanup(sctx->curl);
1193
sctx->curl = NULL;
1194
sctx->sockbuf[0] = '\0';
1195
}
1196
pthread_mutex_unlock(&sctx->sock_lock);
1197
}
1198
1199
static const char *get_stratum_session_id(json_t *val)
1200
{
1201
json_t *arr_val;
1202
int i, n;
1203
1204
arr_val = json_array_get(val, 0);
1205
if (!arr_val || !json_is_array(arr_val))
1206
return NULL;
1207
n = (int) json_array_size(arr_val);
1208
for (i = 0; i < n; i++) {
1209
const char *notify;
1210
json_t *arr = json_array_get(arr_val, i);
1211
1212
if (!arr || !json_is_array(arr))
1213
break;
1214
notify = json_string_value(json_array_get(arr, 0));
1215
if (!notify)
1216
continue;
1217
if (!strcasecmp(notify, "mining.notify"))
1218
return json_string_value(json_array_get(arr, 1));
1219
}
1220
return NULL;
1221
}
1222
1223
static bool stratum_parse_extranonce(struct stratum_ctx *sctx, json_t *params, int pndx)
1224
{
1225
const char* xnonce1;
1226
int xn2_size;
1227
1228
xnonce1 = json_string_value(json_array_get(params, pndx));
1229
if (!xnonce1) {
1230
applog(LOG_ERR, "Failed to get extranonce1");
1231
goto out;
1232
}
1233
xn2_size = (int) json_integer_value(json_array_get(params, pndx+1));
1234
if (!xn2_size) {
1235
applog(LOG_ERR, "Failed to get extranonce2_size");
1236
goto out;
1237
}
1238
if (xn2_size < 2 || xn2_size > 16) {
1239
applog(LOG_INFO, "Failed to get valid n2size in parse_extranonce");
1240
goto out;
1241
}
1242
1243
pthread_mutex_lock(&sctx->work_lock);
1244
if (sctx->xnonce1)
1245
free(sctx->xnonce1);
1246
sctx->xnonce1_size = strlen(xnonce1) / 2;
1247
sctx->xnonce1 = (uchar*) calloc(1, sctx->xnonce1_size);
1248
if (unlikely(!sctx->xnonce1)) {
1249
applog(LOG_ERR, "Failed to alloc xnonce1");
1250
pthread_mutex_unlock(&sctx->work_lock);
1251
goto out;
1252
}
1253
hex2bin(sctx->xnonce1, xnonce1, sctx->xnonce1_size);
1254
sctx->xnonce2_size = xn2_size;
1255
pthread_mutex_unlock(&sctx->work_lock);
1256
1257
if (pndx == 0 && opt_debug) /* pool dynamic change */
1258
applog(LOG_DEBUG, "Stratum set nonce %s with extranonce2 size=%d",
1259
xnonce1, xn2_size);
1260
1261
return true;
1262
out:
1263
return false;
1264
}
1265
1266
bool stratum_subscribe(struct stratum_ctx *sctx)
1267
{
1268
char *s, *sret = NULL;
1269
const char *sid;
1270
json_t *val = NULL, *res_val, *err_val;
1271
json_error_t err;
1272
bool ret = false, retry = false;
1273
1274
if (jsonrpc_2)
1275
return true;
1276
1277
start:
1278
s = (char*) malloc(128 + (sctx->session_id ? strlen(sctx->session_id) : 0));
1279
if (retry)
1280
sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": []}");
1281
else if (sctx->session_id)
1282
sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"" USER_AGENT "\", \"%s\"]}", sctx->session_id);
1283
else
1284
sprintf(s, "{\"id\": 1, \"method\": \"mining.subscribe\", \"params\": [\"" USER_AGENT "\"]}");
1285
1286
if (!stratum_send_line(sctx, s)) {
1287
applog(LOG_ERR, "stratum_subscribe send failed");
1288
goto out;
1289
}
1290
1291
if (!socket_full(sctx->sock, 30)) {
1292
applog(LOG_ERR, "stratum_subscribe timed out");
1293
goto out;
1294
}
1295
1296
sret = stratum_recv_line(sctx);
1297
if (!sret)
1298
goto out;
1299
1300
val = JSON_LOADS(sret, &err);
1301
free(sret);
1302
if (!val) {
1303
applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
1304
goto out;
1305
}
1306
1307
res_val = json_object_get(val, "result");
1308
err_val = json_object_get(val, "error");
1309
1310
if (!res_val || json_is_null(res_val) ||
1311
(err_val && !json_is_null(err_val))) {
1312
if (opt_debug || retry) {
1313
free(s);
1314
if (err_val)
1315
s = json_dumps(err_val, JSON_INDENT(3));
1316
else
1317
s = strdup("(unknown reason)");
1318
applog(LOG_ERR, "JSON-RPC call failed: %s", s);
1319
}
1320
goto out;
1321
}
1322
1323
sid = get_stratum_session_id(res_val);
1324
if (opt_debug && sid)
1325
applog(LOG_DEBUG, "Stratum session id: %s", sid);
1326
1327
pthread_mutex_lock(&sctx->work_lock);
1328
if (sctx->session_id)
1329
free(sctx->session_id);
1330
sctx->session_id = sid ? strdup(sid) : NULL;
1331
sctx->next_diff = 1.0;
1332
pthread_mutex_unlock(&sctx->work_lock);
1333
1334
// sid is param 1, extranonce params are 2 and 3
1335
if (!stratum_parse_extranonce(sctx, res_val, 1)) {
1336
goto out;
1337
}
1338
1339
ret = true;
1340
1341
out:
1342
free(s);
1343
if (val)
1344
json_decref(val);
1345
1346
if (!ret) {
1347
if (sret && !retry) {
1348
retry = true;
1349
goto start;
1350
}
1351
}
1352
1353
return ret;
1354
}
1355
1356
extern bool opt_extranonce;
1357
1358
bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass)
1359
{
1360
json_t *val = NULL, *res_val, *err_val;
1361
char *s, *sret;
1362
json_error_t err;
1363
bool ret = false;
1364
int req_id = 0;
1365
1366
if (jsonrpc_2) {
1367
s = (char*) malloc(300 + strlen(user) + strlen(pass));
1368
sprintf(s, "{\"method\": \"login\", \"params\": {"
1369
"\"login\": \"%s\", \"pass\": \"%s\", \"agent\": \"%s\"}, \"id\": 1}",
1370
user, pass, USER_AGENT);
1371
} else {
1372
s = (char*) malloc(80 + strlen(user) + strlen(pass));
1373
sprintf(s, "{\"id\": 2, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}",
1374
user, pass);
1375
}
1376
1377
if (!stratum_send_line(sctx, s))
1378
goto out;
1379
1380
while (1) {
1381
sret = stratum_recv_line(sctx);
1382
if (!sret)
1383
goto out;
1384
if (!stratum_handle_method(sctx, sret))
1385
break;
1386
free(sret);
1387
}
1388
1389
val = JSON_LOADS(sret, &err);
1390
free(sret);
1391
if (!val) {
1392
applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
1393
goto out;
1394
}
1395
1396
res_val = json_object_get(val, "result");
1397
err_val = json_object_get(val, "error");
1398
req_id = (int) json_integer_value(json_object_get(val, "id"));
1399
1400
if (req_id == 2
1401
&& (!res_val || json_is_false(res_val) || (err_val && !json_is_null(err_val)))) {
1402
applog(LOG_ERR, "Stratum authentication failed");
1403
goto out;
1404
}
1405
1406
if (jsonrpc_2) {
1407
rpc2_login_decode(val);
1408
json_t *job_val = json_object_get(res_val, "job");
1409
pthread_mutex_lock(&sctx->work_lock);
1410
if(job_val) rpc2_job_decode(job_val, &sctx->work);
1411
pthread_mutex_unlock(&sctx->work_lock);
1412
}
1413
1414
ret = true;
1415
1416
if (!opt_extranonce)
1417
goto out;
1418
1419
// subscribe to extranonce (optional)
1420
sprintf(s, "{\"id\": 3, \"method\": \"mining.extranonce.subscribe\", \"params\": []}");
1421
1422
if (!stratum_send_line(sctx, s))
1423
goto out;
1424
1425
if (!socket_full(sctx->sock, 3)) {
1426
if (opt_debug)
1427
applog(LOG_DEBUG, "stratum extranonce subscribe timed out");
1428
goto out;
1429
}
1430
1431
sret = stratum_recv_line(sctx);
1432
if (sret) {
1433
json_t *extra = JSON_LOADS(sret, &err);
1434
if (!extra) {
1435
applog(LOG_WARNING, "JSON decode failed(%d): %s", err.line, err.text);
1436
} else {
1437
if (json_integer_value(json_object_get(extra, "id")) != 3) {
1438
// we receive a standard method if extranonce is ignored
1439
if (!stratum_handle_method(sctx, sret))
1440
applog(LOG_WARNING, "Stratum answer id is not correct!");
1441
}
1442
json_decref(extra);
1443
}
1444
free(sret);
1445
}
1446
1447
out:
1448
free(s);
1449
if (val)
1450
json_decref(val);
1451
1452
return ret;
1453
}
1454
1455
// -------------------- RPC 2.0 (XMR/AEON) -------------------------
1456
1457
extern pthread_mutex_t rpc2_login_lock;
1458
extern pthread_mutex_t rpc2_job_lock;
1459
1460
bool rpc2_login_decode(const json_t *val)
1461
{
1462
const char *id;
1463
const char *s;
1464
1465
json_t *res = json_object_get(val, "result");
1466
if(!res) {
1467
applog(LOG_ERR, "JSON invalid result");
1468
goto err_out;
1469
}
1470
1471
json_t *tmp;
1472
tmp = json_object_get(res, "id");
1473
if(!tmp) {
1474
applog(LOG_ERR, "JSON inval id");
1475
goto err_out;
1476
}
1477
id = json_string_value(tmp);
1478
if(!id) {
1479
applog(LOG_ERR, "JSON id is not a string");
1480
goto err_out;
1481
}
1482
1483
memcpy(&rpc2_id, id, 64);
1484
1485
if(opt_debug)
1486
applog(LOG_DEBUG, "Auth id: %s", id);
1487
1488
tmp = json_object_get(res, "status");
1489
if(!tmp) {
1490
applog(LOG_ERR, "JSON inval status");
1491
goto err_out;
1492
}
1493
s = json_string_value(tmp);
1494
if(!s) {
1495
applog(LOG_ERR, "JSON status is not a string");
1496
goto err_out;
1497
}
1498
if(strcmp(s, "OK")) {
1499
applog(LOG_ERR, "JSON returned status \"%s\"", s);
1500
return false;
1501
}
1502
1503
return true;
1504
1505
err_out:
1506
applog(LOG_WARNING,"%s: fail", __func__);
1507
return false;
1508
}
1509
1510
json_t* json_rpc2_call_recur(CURL *curl, const char *url, const char *userpass,
1511
json_t *rpc_req, int *curl_err, int flags, int recur)
1512
{
1513
if(recur >= 5) {
1514
if(opt_debug)
1515
applog(LOG_DEBUG, "Failed to call rpc command after %i tries", recur);
1516
return NULL;
1517
}
1518
if(!strcmp(rpc2_id, "")) {
1519
if(opt_debug)
1520
applog(LOG_DEBUG, "Tried to call rpc2 command before authentication");
1521
return NULL;
1522
}
1523
json_t *params = json_object_get(rpc_req, "params");
1524
if (params) {
1525
json_t *auth_id = json_object_get(params, "id");
1526
if (auth_id) {
1527
json_string_set(auth_id, rpc2_id);
1528
}
1529
}
1530
json_t *res = json_rpc_call(curl, url, userpass, json_dumps(rpc_req, 0),
1531
curl_err, flags | JSON_RPC_IGNOREERR);
1532
if(!res) goto end;
1533
json_t *error = json_object_get(res, "error");
1534
if(!error) goto end;
1535
json_t *message;
1536
if(json_is_string(error))
1537
message = error;
1538
else
1539
message = json_object_get(error, "message");
1540
if(!message || !json_is_string(message)) goto end;
1541
const char *mes = json_string_value(message);
1542
if(!strcmp(mes, "Unauthenticated")) {
1543
pthread_mutex_lock(&rpc2_login_lock);
1544
rpc2_login(curl);
1545
sleep(1);
1546
pthread_mutex_unlock(&rpc2_login_lock);
1547
return json_rpc2_call_recur(curl, url, userpass, rpc_req,
1548
curl_err, flags, recur + 1);
1549
} else if(!strcmp(mes, "Low difficulty share") || !strcmp(mes, "Block expired") || !strcmp(mes, "Invalid job id") || !strcmp(mes, "Duplicate share")) {
1550
json_t *result = json_object_get(res, "result");
1551
if(!result) {
1552
goto end;
1553
}
1554
json_object_set(result, "reject-reason", json_string(mes));
1555
} else {
1556
applog(LOG_ERR, "json_rpc2.0 error: %s", mes);
1557
return NULL;
1558
}
1559
end:
1560
return res;
1561
}
1562
1563
json_t *json_rpc2_call(CURL *curl, const char *url, const char *userpass, const char *rpc_req, int *curl_err, int flags)
1564
{
1565
json_t* req_json = JSON_LOADS(rpc_req, NULL);
1566
json_t* res = json_rpc2_call_recur(curl, url, userpass, req_json, curl_err, flags, 0);
1567
json_decref(req_json);
1568
return res;
1569
}
1570
1571
bool rpc2_job_decode(const json_t *job, struct work *work)
1572
{
1573
if (!jsonrpc_2) {
1574
applog(LOG_ERR, "Tried to decode job without JSON-RPC 2.0");
1575
return false;
1576
}
1577
json_t *tmp;
1578
tmp = json_object_get(job, "job_id");
1579
if (!tmp) {
1580
applog(LOG_ERR, "JSON invalid job id");
1581
goto err_out;
1582
}
1583
const char *job_id = json_string_value(tmp);
1584
tmp = json_object_get(job, "blob");
1585
if (!tmp) {
1586
applog(LOG_ERR, "JSON invalid blob");
1587
goto err_out;
1588
}
1589
const char *hexblob = json_string_value(tmp);
1590
size_t blobLen = strlen(hexblob);
1591
if (blobLen % 2 != 0 || ((blobLen / 2) < 40 && blobLen != 0) || (blobLen / 2) > 128) {
1592
applog(LOG_ERR, "JSON invalid blob length");
1593
goto err_out;
1594
}
1595
if (blobLen != 0) {
1596
uint32_t target = 0;
1597
pthread_mutex_lock(&rpc2_job_lock);
1598
uchar *blob = (uchar*) malloc(blobLen / 2);
1599
if (!hex2bin(blob, hexblob, blobLen / 2)) {
1600
applog(LOG_ERR, "JSON invalid blob");
1601
pthread_mutex_unlock(&rpc2_job_lock);
1602
goto err_out;
1603
}
1604
rpc2_bloblen = blobLen / 2;
1605
if (rpc2_blob) free(rpc2_blob);
1606
rpc2_blob = (char*) malloc(rpc2_bloblen);
1607
if (!rpc2_blob) {
1608
applog(LOG_ERR, "RPC2 OOM!");
1609
goto err_out;
1610
}
1611
memcpy(rpc2_blob, blob, blobLen / 2);
1612
free(blob);
1613
1614
jobj_binary(job, "target", &target, 4);
1615
if(rpc2_target != target) {
1616
double hashrate = 0.0;
1617
pthread_mutex_lock(&stats_lock);
1618
for (int i = 0; i < opt_n_threads; i++)
1619
hashrate += thr_hashrates[i];
1620
pthread_mutex_unlock(&stats_lock);
1621
double difficulty = (((double) 0xffffffff) / target);
1622
if (!opt_quiet) {
1623
// xmr pool diff can change a lot...
1624
applog(LOG_WARNING, "Stratum difficulty set to %g", difficulty);
1625
}
1626
stratum_diff = difficulty;
1627
rpc2_target = target;
1628
}
1629
1630
if (rpc2_job_id) free(rpc2_job_id);
1631
rpc2_job_id = strdup(job_id);
1632
pthread_mutex_unlock(&rpc2_job_lock);
1633
}
1634
if(work) {
1635
if (!rpc2_blob) {
1636
applog(LOG_WARNING, "Work requested before it was received");
1637
goto err_out;
1638
}
1639
memcpy(work->data, rpc2_blob, rpc2_bloblen);
1640
memset(work->target, 0xff, sizeof(work->target));
1641
work->target[7] = rpc2_target;
1642
if (work->job_id) free(work->job_id);
1643
work->job_id = strdup(rpc2_job_id);
1644
}
1645
return true;
1646
1647
err_out:
1648
applog(LOG_WARNING, "%s", __func__);
1649
return false;
1650
}
1651
1652
/**
1653
* Extract bloc height L H... here len=3, height=0x1333e8
1654
* "...0000000000ffffffff2703e83313062f503253482f043d61105408"
1655
*/
1656
static uint32_t getblocheight(struct stratum_ctx *sctx)
1657
{
1658
uint32_t height = 0;
1659
uint8_t hlen = 0, *p, *m;
1660
1661
// find 0xffff tag
1662
p = (uint8_t*) sctx->job.coinbase + 32;
1663
m = p + 128;
1664
while (*p != 0xff && p < m) p++;
1665
while (*p == 0xff && p < m) p++;
1666
if (*(p-1) == 0xff && *(p-2) == 0xff) {
1667
p++; hlen = *p;
1668
p++; height = le16dec(p);
1669
p += 2;
1670
switch (hlen) {
1671
case 4:
1672
height += 0x10000UL * le16dec(p);
1673
break;
1674
case 3:
1675
height += 0x10000UL * (*p);
1676
break;
1677
}
1678
}
1679
return height;
1680
}
1681
1682
static bool stratum_notify(struct stratum_ctx *sctx, json_t *params)
1683
{
1684
char algo[64] = { 0 };
1685
const char *job_id, *prevhash, *coinb1, *coinb2, *version, *nbits, *ntime;
1686
const char *extradata = NULL;
1687
size_t coinb1_size, coinb2_size;
1688
bool clean, ret = false;
1689
int merkle_count, i, p=0;
1690
bool has_claim, has_roots;
1691
json_t *merkle_arr;
1692
uchar **merkle;
1693
1694
get_currentalgo(algo, sizeof(algo));
1695
has_claim = strcmp(algo, "lbry") == 0 && json_array_size(params) == 10;
1696
has_roots = strcmp(algo, "phi2") == 0 && json_array_size(params) == 10;
1697
1698
job_id = json_string_value(json_array_get(params, p++));
1699
prevhash = json_string_value(json_array_get(params, p++));
1700
if (has_claim) {
1701
extradata = json_string_value(json_array_get(params, p++));
1702
if (!extradata || strlen(extradata) != 64) {
1703
applog(LOG_ERR, "Stratum notify: invalid claim parameter");
1704
goto out;
1705
}
1706
}
1707
else if (has_roots) {
1708
extradata = json_string_value(json_array_get(params, p++));
1709
if (!extradata || strlen(extradata) != 128) {
1710
applog(LOG_ERR, "Stratum notify: invalid UTXO root parameter");
1711
goto out;
1712
}
1713
}
1714
coinb1 = json_string_value(json_array_get(params, p++));
1715
coinb2 = json_string_value(json_array_get(params, p++));
1716
merkle_arr = json_array_get(params, p++);
1717
if (!merkle_arr || !json_is_array(merkle_arr))
1718
goto out;
1719
merkle_count = (int) json_array_size(merkle_arr);
1720
version = json_string_value(json_array_get(params, p++));
1721
nbits = json_string_value(json_array_get(params, p++));
1722
ntime = json_string_value(json_array_get(params, p++));
1723
clean = json_is_true(json_array_get(params, p));
1724
1725
if (!job_id || !prevhash || !coinb1 || !coinb2 || !version || !nbits || !ntime ||
1726
strlen(prevhash) != 64 || strlen(version) != 8 ||
1727
strlen(nbits) != 8 || strlen(ntime) != 8) {
1728
applog(LOG_ERR, "Stratum notify: invalid parameters");
1729
goto out;
1730
}
1731
merkle = (uchar**) malloc(merkle_count * sizeof(char *));
1732
for (i = 0; i < merkle_count; i++) {
1733
const char *s = json_string_value(json_array_get(merkle_arr, i));
1734
if (!s || strlen(s) != 64) {
1735
while (i--)
1736
free(merkle[i]);
1737
free(merkle);
1738
applog(LOG_ERR, "Stratum notify: invalid Merkle branch");
1739
goto out;
1740
}
1741
merkle[i] = (uchar*) malloc(32);
1742
hex2bin(merkle[i], s, 32);
1743
}
1744
1745
pthread_mutex_lock(&sctx->work_lock);
1746
1747
coinb1_size = strlen(coinb1) / 2;
1748
coinb2_size = strlen(coinb2) / 2;
1749
sctx->job.coinbase_size = coinb1_size + sctx->xnonce1_size +
1750
sctx->xnonce2_size + coinb2_size;
1751
sctx->job.coinbase = (uchar*) realloc(sctx->job.coinbase, sctx->job.coinbase_size);
1752
sctx->job.xnonce2 = sctx->job.coinbase + coinb1_size + sctx->xnonce1_size;
1753
hex2bin(sctx->job.coinbase, coinb1, coinb1_size);
1754
memcpy(sctx->job.coinbase + coinb1_size, sctx->xnonce1, sctx->xnonce1_size);
1755
if (!sctx->job.job_id || strcmp(sctx->job.job_id, job_id))
1756
memset(sctx->job.xnonce2, 0, sctx->xnonce2_size);
1757
hex2bin(sctx->job.xnonce2 + sctx->xnonce2_size, coinb2, coinb2_size);
1758
1759
free(sctx->job.job_id);
1760
sctx->job.job_id = strdup(job_id);
1761
hex2bin(sctx->job.prevhash, prevhash, 32);
1762
1763
if (has_claim) hex2bin(sctx->job.extra, extradata, 32);
1764
if (has_roots) hex2bin(sctx->job.extra, extradata, 64);
1765
1766
sctx->bloc_height = getblocheight(sctx);
1767
1768
for (i = 0; i < sctx->job.merkle_count; i++)
1769
free(sctx->job.merkle[i]);
1770
free(sctx->job.merkle);
1771
sctx->job.merkle = merkle;
1772
sctx->job.merkle_count = merkle_count;
1773
1774
hex2bin(sctx->job.version, version, 4);
1775
hex2bin(sctx->job.nbits, nbits, 4);
1776
hex2bin(sctx->job.ntime, ntime, 4);
1777
sctx->job.clean = clean;
1778
1779
sctx->job.diff = sctx->next_diff;
1780
1781
pthread_mutex_unlock(&sctx->work_lock);
1782
1783
ret = true;
1784
1785
out:
1786
return ret;
1787
}
1788
1789
static bool stratum_set_difficulty(struct stratum_ctx *sctx, json_t *params)
1790
{
1791
double diff;
1792
1793
diff = json_number_value(json_array_get(params, 0));
1794
if (diff == 0)
1795
return false;
1796
1797
pthread_mutex_lock(&sctx->work_lock);
1798
sctx->next_diff = diff;
1799
pthread_mutex_unlock(&sctx->work_lock);
1800
1801
return true;
1802
}
1803
1804
static bool stratum_reconnect(struct stratum_ctx *sctx, json_t *params)
1805
{
1806
json_t *port_val;
1807
char *url;
1808
const char *host;
1809
int port;
1810
1811
host = json_string_value(json_array_get(params, 0));
1812
port_val = json_array_get(params, 1);
1813
if (json_is_string(port_val))
1814
port = atoi(json_string_value(port_val));
1815
else
1816
port = (int) json_integer_value(port_val);
1817
if (!host || !port)
1818
return false;
1819
1820
url = (char*) malloc(32 + strlen(host));
1821
sprintf(url, "stratum+tcp://%s:%d", host, port);
1822
1823
if (!opt_redirect) {
1824
applog(LOG_INFO, "Ignoring request to reconnect to %s", url);
1825
free(url);
1826
return true;
1827
}
1828
1829
applog(LOG_NOTICE, "Server requested reconnection to %s", url);
1830
1831
free(sctx->url);
1832
sctx->url = url;
1833
stratum_disconnect(sctx);
1834
1835
return true;
1836
}
1837
1838
static bool json_object_set_error(json_t *result, int code, const char *msg)
1839
{
1840
json_t *val = json_object();
1841
json_object_set_new(val, "code", json_integer(code));
1842
json_object_set_new(val, "message", json_string(msg));
1843
return json_object_set_new(result, "error", val) != -1;
1844
}
1845
1846
/* allow to report algo perf to the pool for algo stats */
1847
static bool stratum_benchdata(json_t *result, json_t *params, int thr_id)
1848
{
1849
char algo[64] = { 0 };
1850
char cpuname[80] = { 0 };
1851
char vendorid[32] = { 0 };
1852
char compiler[32] = { 0 };
1853
char arch[16] = { 0 };
1854
char os[8];
1855
char *p;
1856
double cpufreq = 0;
1857
json_t *val;
1858
1859
if (!opt_stratum_stats) return false;
1860
1861
get_currentalgo(algo, sizeof(algo));
1862
1863
#if defined(WIN32) && (defined(_M_X64) || defined(__x86_64__))
1864
strcpy(os, "win64");
1865
#else
1866
strcpy(os, is_windows() ? "win32" : "linux");
1867
#endif
1868
1869
#ifdef _MSC_VER
1870
sprintf(compiler, "MSVC %d\n", msver());
1871
#elif defined(__clang__)
1872
sprintf(compiler, "clang %s\n", __clang_version__);
1873
#elif defined(__GNUC__)
1874
sprintf(compiler, "GCC %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
1875
#endif
1876
1877
#ifdef __AVX2__
1878
strcat(compiler, " AVX2");
1879
#elif defined(__AVX__)
1880
strcat(compiler, " AVX");
1881
#elif defined(__FMA4__)
1882
strcat(compiler, " FMA4");
1883
#elif defined(__FMA3__)
1884
strcat(compiler, " FMA3");
1885
#elif defined(__SSE4_2__)
1886
strcat(compiler, " SSE4.2");
1887
#elif defined(__SSE4_1__)
1888
strcat(compiler, " SSE4");
1889
#elif defined(__SSE3__)
1890
strcat(compiler, " SSE3");
1891
#elif defined(__SSE2__)
1892
strcat(compiler, " SSE2");
1893
#elif defined(__SSE__)
1894
strcat(compiler, " SSE");
1895
#endif
1896
1897
cpu_bestfeature(arch, 16);
1898
if (has_aes_ni()) strcat(arch, " NI");
1899
1900
cpu_getmodelid(vendorid, 32);
1901
cpu_getname(cpuname, 80);
1902
p = strstr(cpuname, " @ ");
1903
if (p) {
1904
char freq[32] = { 0 };
1905
*p = '\0'; p += 3;
1906
snprintf(freq, 32, "%s", p);
1907
cpufreq = atof(freq);
1908
p = strstr(freq, "GHz"); if (p) cpufreq *= 1000;
1909
applog(LOG_NOTICE, "sharing CPU stats with freq %s", freq);
1910
}
1911
1912
compiler[31] = '\0';
1913
1914
val = json_object();
1915
json_object_set_new(val, "algo", json_string(algo));
1916
json_object_set_new(val, "type", json_string("cpu"));
1917
json_object_set_new(val, "device", json_string(cpuname));
1918
json_object_set_new(val, "vendorid", json_string(vendorid));
1919
json_object_set_new(val, "arch", json_string(arch));
1920
json_object_set_new(val, "freq", json_integer((uint64_t)cpufreq));
1921
json_object_set_new(val, "memf", json_integer(0));
1922
json_object_set_new(val, "power", json_integer(0));
1923
json_object_set_new(val, "khashes", json_real((double)global_hashrate / 1000.0));
1924
json_object_set_new(val, "intensity", json_real(opt_priority));
1925
json_object_set_new(val, "throughput", json_integer(opt_n_threads));
1926
json_object_set_new(val, "client", json_string(PACKAGE_NAME "/" PACKAGE_VERSION));
1927
json_object_set_new(val, "os", json_string(os));
1928
json_object_set_new(val, "driver", json_string(compiler));
1929
1930
json_object_set_new(result, "result", val);
1931
1932
return true;
1933
}
1934
1935
static bool stratum_get_stats(struct stratum_ctx *sctx, json_t *id, json_t *params)
1936
{
1937
char *s;
1938
json_t *val;
1939
bool ret;
1940
1941
if (!id || json_is_null(id))
1942
return false;
1943
1944
val = json_object();
1945
json_object_set(val, "id", id);
1946
1947
ret = stratum_benchdata(val, params, 0);
1948
1949
if (!ret) {
1950
json_object_set_error(val, 1, "disabled"); //EPERM
1951
} else {
1952
json_object_set_new(val, "error", json_null());
1953
}
1954
1955
s = json_dumps(val, 0);
1956
ret = stratum_send_line(sctx, s);
1957
json_decref(val);
1958
free(s);
1959
1960
return ret;
1961
}
1962
1963
static bool stratum_unknown_method(struct stratum_ctx *sctx, json_t *id)
1964
{
1965
char *s;
1966
json_t *val;
1967
bool ret = false;
1968
1969
if (!id || json_is_null(id))
1970
return ret;
1971
1972
val = json_object();
1973
json_object_set(val, "id", id);
1974
json_object_set_new(val, "result", json_false());
1975
json_object_set_error(val, 38, "unknown method"); // ENOSYS
1976
1977
s = json_dumps(val, 0);
1978
ret = stratum_send_line(sctx, s);
1979
json_decref(val);
1980
free(s);
1981
1982
return ret;
1983
}
1984
1985
static bool stratum_pong(struct stratum_ctx *sctx, json_t *id)
1986
{
1987
char buf[64];
1988
bool ret = false;
1989
1990
if (!id || json_is_null(id))
1991
return ret;
1992
1993
sprintf(buf, "{\"id\":%d,\"result\":\"pong\",\"error\":null}",
1994
(int) json_integer_value(id));
1995
ret = stratum_send_line(sctx, buf);
1996
1997
return ret;
1998
}
1999
2000
static bool stratum_get_algo(struct stratum_ctx *sctx, json_t *id, json_t *params)
2001
{
2002
char algo[64] = { 0 };
2003
char *s;
2004
json_t *val;
2005
bool ret = true;
2006
2007
if (!id || json_is_null(id))
2008
return false;
2009
2010
get_currentalgo(algo, sizeof(algo));
2011
2012
val = json_object();
2013
json_object_set(val, "id", id);
2014
json_object_set_new(val, "error", json_null());
2015
json_object_set_new(val, "result", json_string(algo));
2016
2017
s = json_dumps(val, 0);
2018
ret = stratum_send_line(sctx, s);
2019
json_decref(val);
2020
free(s);
2021
2022
return ret;
2023
}
2024
2025
static bool stratum_get_version(struct stratum_ctx *sctx, json_t *id)
2026
{
2027
char *s;
2028
json_t *val;
2029
bool ret;
2030
2031
if (!id || json_is_null(id))
2032
return false;
2033
2034
val = json_object();
2035
json_object_set(val, "id", id);
2036
json_object_set_new(val, "error", json_null());
2037
json_object_set_new(val, "result", json_string(USER_AGENT));
2038
s = json_dumps(val, 0);
2039
ret = stratum_send_line(sctx, s);
2040
json_decref(val);
2041
free(s);
2042
2043
return ret;
2044
}
2045
2046
static bool stratum_show_message(struct stratum_ctx *sctx, json_t *id, json_t *params)
2047
{
2048
char *s;
2049
json_t *val;
2050
bool ret;
2051
2052
val = json_array_get(params, 0);
2053
if (val)
2054
applog(LOG_NOTICE, "MESSAGE FROM SERVER: %s", json_string_value(val));
2055
2056
if (!id || json_is_null(id))
2057
return true;
2058
2059
val = json_object();
2060
json_object_set(val, "id", id);
2061
json_object_set_new(val, "error", json_null());
2062
json_object_set_new(val, "result", json_true());
2063
s = json_dumps(val, 0);
2064
ret = stratum_send_line(sctx, s);
2065
json_decref(val);
2066
free(s);
2067
2068
return ret;
2069
}
2070
2071
bool stratum_handle_method(struct stratum_ctx *sctx, const char *s)
2072
{
2073
json_t *val, *id, *params;
2074
json_error_t err;
2075
const char *method;
2076
bool ret = false;
2077
2078
val = JSON_LOADS(s, &err);
2079
if (!val) {
2080
applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text);
2081
goto out;
2082
}
2083
2084
method = json_string_value(json_object_get(val, "method"));
2085
if (!method)
2086
goto out;
2087
2088
params = json_object_get(val, "params");
2089
2090
if (jsonrpc_2) {
2091
if (!strcasecmp(method, "job")) {
2092
ret = rpc2_stratum_job(sctx, params);
2093
}
2094
goto out;
2095
}
2096
2097
id = json_object_get(val, "id");
2098
2099
if (!strcasecmp(method, "mining.notify")) {
2100
ret = stratum_notify(sctx, params);
2101
goto out;
2102
}
2103
if (!strcasecmp(method, "mining.ping")) { // cgminer 4.7.1+
2104
if (opt_debug) applog(LOG_DEBUG, "Pool ping");
2105
ret = stratum_pong(sctx, id);
2106
goto out;
2107
}
2108
if (!strcasecmp(method, "mining.set_difficulty")) {
2109
ret = stratum_set_difficulty(sctx, params);
2110
goto out;
2111
}
2112
if (!strcasecmp(method, "mining.set_extranonce")) {
2113
ret = stratum_parse_extranonce(sctx, params, 0);
2114
goto out;
2115
}
2116
if (!strcasecmp(method, "client.reconnect")) {
2117
ret = stratum_reconnect(sctx, params);
2118
goto out;
2119
}
2120
if (!strcasecmp(method, "client.get_algo")) {
2121
// will prevent wrong algo parameters on a pool, will be used as test on rejects
2122
if (!opt_quiet) applog(LOG_NOTICE, "Pool asked your algo parameter");
2123
ret = stratum_get_algo(sctx, id, params);
2124
goto out;
2125
}
2126
if (!strcasecmp(method, "client.get_stats")) {
2127
// optional to fill device benchmarks
2128
ret = stratum_get_stats(sctx, id, params);
2129
goto out;
2130
}
2131
if (!strcasecmp(method, "client.get_version")) {
2132
ret = stratum_get_version(sctx, id);
2133
goto out;
2134
}
2135
if (!strcasecmp(method, "client.show_message")) {
2136
ret = stratum_show_message(sctx, id, params);
2137
goto out;
2138
}
2139
2140
if (!ret) {
2141
// don't fail = disconnect stratum on unknown (and optional?) methods
2142
if (opt_debug) applog(LOG_WARNING, "unknown stratum method %s!", method);
2143
ret = stratum_unknown_method(sctx, id);
2144
}
2145
2146
out:
2147
if (val)
2148
json_decref(val);
2149
2150
return ret;
2151
}
2152
2153
struct thread_q *tq_new(void)
2154
{
2155
struct thread_q *tq;
2156
2157
tq = (struct thread_q*) calloc(1, sizeof(*tq));
2158
if (!tq)
2159
return NULL;
2160
2161
INIT_LIST_HEAD(&tq->q);
2162
pthread_mutex_init(&tq->mutex, NULL);
2163
pthread_cond_init(&tq->cond, NULL);
2164
2165
return tq;
2166
}
2167
2168
void tq_free(struct thread_q *tq)
2169
{
2170
struct tq_ent *ent, *iter;
2171
2172
if (!tq)
2173
return;
2174
2175
list_for_each_entry_safe(ent, iter, &tq->q, q_node, struct tq_ent) {
2176
list_del(&ent->q_node);
2177
free(ent);
2178
}
2179
2180
pthread_cond_destroy(&tq->cond);
2181
pthread_mutex_destroy(&tq->mutex);
2182
2183
memset(tq, 0, sizeof(*tq)); /* poison */
2184
free(tq);
2185
}
2186
2187
static void tq_freezethaw(struct thread_q *tq, bool frozen)
2188
{
2189
pthread_mutex_lock(&tq->mutex);
2190
2191
tq->frozen = frozen;
2192
2193
pthread_cond_signal(&tq->cond);
2194
pthread_mutex_unlock(&tq->mutex);
2195
}
2196
2197
void tq_freeze(struct thread_q *tq)
2198
{
2199
tq_freezethaw(tq, true);
2200
}
2201
2202
void tq_thaw(struct thread_q *tq)
2203
{
2204
tq_freezethaw(tq, false);
2205
}
2206
2207
bool tq_push(struct thread_q *tq, void *data)
2208
{
2209
struct tq_ent *ent;
2210
bool rc = true;
2211
2212
ent = (struct tq_ent*) calloc(1, sizeof(*ent));
2213
if (!ent)
2214
return false;
2215
2216
ent->data = data;
2217
INIT_LIST_HEAD(&ent->q_node);
2218
2219
pthread_mutex_lock(&tq->mutex);
2220
2221
if (!tq->frozen) {
2222
list_add_tail(&ent->q_node, &tq->q);
2223
} else {
2224
free(ent);
2225
rc = false;
2226
}
2227
2228
pthread_cond_signal(&tq->cond);
2229
pthread_mutex_unlock(&tq->mutex);
2230
2231
return rc;
2232
}
2233
2234
void *tq_pop(struct thread_q *tq, const struct timespec *abstime)
2235
{
2236
struct tq_ent *ent;
2237
void *rval = NULL;
2238
int rc;
2239
2240
pthread_mutex_lock(&tq->mutex);
2241
2242
if (!list_empty(&tq->q))
2243
goto pop;
2244
2245
if (abstime)
2246
rc = pthread_cond_timedwait(&tq->cond, &tq->mutex, abstime);
2247
else
2248
rc = pthread_cond_wait(&tq->cond, &tq->mutex);
2249
if (rc)
2250
goto out;
2251
if (list_empty(&tq->q))
2252
goto out;
2253
2254
pop:
2255
ent = list_entry(tq->q.next, struct tq_ent, q_node);
2256
rval = ent->data;
2257
2258
list_del(&ent->q_node);
2259
free(ent);
2260
2261
out:
2262
pthread_mutex_unlock(&tq->mutex);
2263
return rval;
2264
}
2265
2266
/* sprintf can be used in applog */
2267
static char* format_hash(char* buf, uint8_t *hash)
2268
{
2269
int len = 0;
2270
for (int i=0; i < 32; i += 4) {
2271
len += sprintf(buf+len, "%02x%02x%02x%02x ",
2272
hash[i], hash[i+1], hash[i+2], hash[i+3]);
2273
}
2274
return buf;
2275
}
2276
2277
void applog_compare_hash(void *hash, void *hash_ref)
2278
{
2279
char s[256] = "";
2280
int len = 0;
2281
uchar* hash1 = (uchar*)hash;
2282
uchar* hash2 = (uchar*)hash_ref;
2283
for (int i=0; i < 32; i += 4) {
2284
const char *color = memcmp(hash1+i, hash2+i, 4) ? CL_WHT : CL_GRY;
2285
len += sprintf(s+len, "%s%02x%02x%02x%02x " CL_GRY, color,
2286
hash1[i], hash1[i+1], hash1[i+2], hash1[i+3]);
2287
s[len] = '\0';
2288
}
2289
applog(LOG_DEBUG, "%s", s);
2290
}
2291
2292
void applog_hash(void *hash)
2293
{
2294
char s[128] = {'\0'};
2295
applog(LOG_DEBUG, "%s", format_hash(s, (uchar*) hash));
2296
}
2297
2298
void applog_hex(void *data, int len)
2299
{
2300
char* hex = abin2hex((uchar*)data, len);
2301
applog(LOG_DEBUG, "%s", hex);
2302
free(hex);
2303
}
2304
2305
void applog_hash64(void *hash)
2306
{
2307
char s[128] = {'\0'};
2308
char t[128] = {'\0'};
2309
applog(LOG_DEBUG, "%s %s", format_hash(s, (uchar*)hash), format_hash(t, &((uchar*)hash)[32]));
2310
}
2311
2312
2313
#define printpfx(n,h) \
2314
printf("%s%11s%s: %s\n", CL_CYN, n, CL_N, format_hash(s, (uint8_t*) h))
2315
2316
void print_hash_tests(void)
2317
{
2318
uchar *scratchbuf = NULL;
2319
char hash[128], s[80];
2320
char buf[192] = { 0 };
2321
2322
scratchbuf = (uchar*) calloc(128, 1024);
2323
2324
printf(CL_WHT "CPU HASH ON EMPTY BUFFER RESULTS:" CL_N "\n\n");
2325
2326
memset(buf, 0, sizeof(buf));
2327
//buf[0] = 1; buf[64] = 2; // for endian tests
2328
2329
allium_hash(&hash[0], &buf[0]);
2330
printpfx("allium", hash);
2331
2332
axiomhash(&hash[0], &buf[0]);
2333
printpfx("axiom", hash);
2334
2335
bastionhash(&hash[0], &buf[0]);
2336
printpfx("bastion", hash);
2337
2338
blakehash(&hash[0], &buf[0]);
2339
printpfx("blake", hash);
2340
2341
blakecoinhash(&hash[0], &buf[0]);
2342
printpfx("blakecoin", hash);
2343
2344
blake2b_hash(&hash[0], &buf[0]);
2345
printpfx("blake2b", hash);
2346
2347
blake2s_hash(&hash[0], &buf[0]);
2348
printpfx("blake2s", hash);
2349
2350
bmwhash(&hash[0], &buf[0]);
2351
printpfx("bmw", hash);
2352
2353
c11hash(&hash[0], &buf[0]);
2354
printpfx("c11", hash);
2355
2356
cryptolight_hash(&hash[0], &buf[0]);
2357
printpfx("cryptolight", hash);
2358
2359
cryptonight_hash_v1(&hash[0], &buf[0]);
2360
printpfx("cryptonight", hash);
2361
2362
decred_hash(&hash[0], &buf[0]);
2363
printpfx("decred", hash);
2364
2365
droplp_hash(&hash[0], &buf[0]);
2366
printpfx("drop", hash);
2367
2368
freshhash(&hash[0], &buf[0], 80);
2369
printpfx("fresh", hash);
2370
2371
geekhash(&hash[0], &buf[0]);
2372
printpfx("geek", hash);
2373
2374
groestlhash(&hash[0], &buf[0]);
2375
printpfx("groestl", hash);
2376
2377
heavyhash((uint8_t*) &hash[0], (uint8_t*) &buf[0], 32);
2378
printpfx("heavy", hash);
2379
2380
keccakhash(&hash[0], &buf[0]);
2381
printpfx("keccak", hash);
2382
2383
jha_hash(&hash[0], &buf[0]);
2384
printpfx("jha", hash);
2385
2386
lbry_hash(&hash[0], &buf[0]);
2387
printpfx("lbry", hash);
2388
2389
luffahash(&hash[0], &buf[0]);
2390
printpfx("luffa", hash);
2391
2392
lyra2_hash(&hash[0], &buf[0]);
2393
printpfx("lyra2", hash);
2394
2395
lyra2rev2_hash(&hash[0], &buf[0]);
2396
printpfx("lyra2v2", hash);
2397
2398
lyra2v3_hash(&hash[0], &buf[0]);
2399
printpfx("lyra2v3", hash);
2400
2401
cryptonight_hash(&hash[0], &buf[0]);
2402
printpfx("monero", hash);
2403
2404
myriadhash(&hash[0], &buf[0]);
2405
printpfx("myr-gr", hash);
2406
2407
neoscrypt((uchar*) &hash[0], (uchar*)&buf[0], 80000620);
2408
printpfx("neoscrypt", hash);
2409
2410
nist5hash(&hash[0], &buf[0]);
2411
printpfx("nist5", hash);
2412
2413
pentablakehash(&hash[0], &buf[0]);
2414
printpfx("pentablake", hash);
2415
2416
phi1612_hash(&hash[0], &buf[0]);
2417
printpfx("phi1612", hash);
2418
2419
phi2_hash(&hash[0], &buf[0]);
2420
printpfx("phi2", hash);
2421
2422
pluck_hash((uint32_t*)&hash[0], (uint32_t*)&buf[0], scratchbuf, 128);
2423
memset(&buf[0], 0, sizeof(buf));
2424
printpfx("pluck", hash);
2425
2426
init_quarkhash_contexts();
2427
quarkhash(&hash[0], &buf[0]);
2428
printpfx("quark", hash);
2429
2430
qubithash(&hash[0], &buf[0]);
2431
printpfx("qubit", hash);
2432
2433
rf256_hash(&hash[0], &buf[0], 80);
2434
printpfx("rainforest", hash);
2435
2436
scrypthash(&hash[0], &buf[0], 1024);
2437
printpfx("scrypt", hash);
2438
2439
scrypthash(&hash[0], &buf[0], 2048);
2440
printpfx("scrypt:2048", hash);
2441
2442
scryptjanehash(&hash[0], &buf[0], 9);
2443
printpfx("scrypt-jane", hash);
2444
2445
inkhash(&hash[0], &buf[0]);
2446
printpfx("shavite3", hash);
2447
2448
sha256d((uint8_t*) &hash[0], (uint8_t*)&buf[0], 64);
2449
printpfx("sha256d", hash);
2450
2451
blake2b_hash(&hash[0], &buf[0]);
2452
printpfx("sia", hash);
2453
2454
sibhash(&hash[0], &buf[0]);
2455
printpfx("sib", hash);
2456
2457
skeinhash(&hash[0], &buf[0]);
2458
printpfx("skein", hash);
2459
2460
skein2hash(&hash[0], &buf[0]);
2461
printpfx("skein2", hash);
2462
2463
sonoa_hash(&hash[0], &buf[0]);
2464
printpfx("sonoa", hash);
2465
2466
s3hash(&hash[0], &buf[0]);
2467
printpfx("s3", hash);
2468
2469
timetravel_hash(&hash[0], &buf[0]);
2470
printpfx("timetravel", hash);
2471
2472
bitcore_hash(&hash[0], &buf[0]);
2473
printpfx("bitcore", hash);
2474
2475
tribus_hash(&hash[0], &buf[0]);
2476
printpfx("tribus", hash);
2477
2478
veltor_hash(&hash[0], &buf[0]);
2479
printpfx("veltor", hash);
2480
2481
xevan_hash(&hash[0], &buf[0]);
2482
printpfx("xevan", hash);
2483
2484
x11evo_hash(&hash[0], &buf[0]);
2485
printpfx("x11evo", hash);
2486
2487
x11hash(&hash[0], &buf[0]);
2488
printpfx("x11", hash);
2489
2490
x12hash(&hash[0], &buf[0]);
2491
printpfx("x12", hash);
2492
2493
x13hash(&hash[0], &buf[0]);
2494
printpfx("x13", hash);
2495
2496
x14hash(&hash[0], &buf[0]);
2497
printpfx("x14", hash);
2498
2499
x15hash(&hash[0], &buf[0]);
2500
printpfx("x15", hash);
2501
2502
x16r_hash(&hash[0], &buf[0]);
2503
//hidden, same as x16rv2 without prevhash
2504
//printpfx("x16r", hash);
2505
2506
x16rv2_hash(&hash[0], &buf[0]);
2507
printpfx("x16rv2", hash);
2508
2509
x16s_hash(&hash[0], &buf[0]);
2510
printpfx("x16s", hash);
2511
2512
x17hash(&hash[0], &buf[0]);
2513
printpfx("x17", hash);
2514
2515
x20r_hash(&hash[0], &buf[0]);
2516
printpfx("x20r", hash);
2517
2518
yescrypthash(&hash[0], &buf[0]);
2519
printpfx("yescrypt", hash);
2520
2521
yescrypt_hash_r8(&buf[0], &hash[0], 80);
2522
printpfx("yescryptr8", hash);
2523
2524
yescrypt_hash_r16(&buf[0], &hash[0], 80);
2525
printpfx("yescryptr16", hash);
2526
2527
yescrypt_hash_r32(&buf[0], &hash[0], 80);
2528
printpfx("yescryptr32", hash);
2529
2530
//zr5hash(&hash[0], &buf[0]);
2531
zr5hash(&hash[0], (uint32_t*) &buf[0]);
2532
memset(buf, 0, sizeof(buf));
2533
printpfx("zr5", hash);
2534
2535
printf("\n");
2536
2537
free(scratchbuf);
2538
}
2539
2540
2541