Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
litecoincash-project
GitHub Repository: litecoincash-project/cpuminer-multi
Path: blob/master/cpu-miner.c
548 views
1
/*
2
* Copyright 2010 Jeff Garzik
3
* Copyright 2012-2014 pooler
4
* Copyright 2014 Lucas Jones
5
* Copyright 2014 Tanguy Pruvot
6
*
7
* This program is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License as published by the Free
9
* Software Foundation; either version 2 of the License, or (at your option)
10
* any later version. See COPYING for more details.
11
*/
12
13
#include <cpuminer-config.h>
14
#define _GNU_SOURCE
15
16
#include <stdio.h>
17
#include <stdlib.h>
18
#include <string.h>
19
#include <stdbool.h>
20
#include <inttypes.h>
21
#include <unistd.h>
22
#include <sys/time.h>
23
#include <time.h>
24
#include <signal.h>
25
26
#include <curl/curl.h>
27
#include <jansson.h>
28
#include <openssl/sha.h>
29
30
#ifdef _MSC_VER
31
#include <windows.h>
32
#include <stdint.h>
33
#else
34
#include <errno.h>
35
#if HAVE_SYS_SYSCTL_H
36
#include <sys/types.h>
37
#if HAVE_SYS_PARAM_H
38
#include <sys/param.h>
39
#endif
40
#include <sys/sysctl.h>
41
#endif
42
#endif
43
44
#ifndef WIN32
45
#include <sys/resource.h>
46
#endif
47
48
#include "miner.h"
49
50
#ifdef WIN32
51
#include "compat/winansi.h"
52
BOOL WINAPI ConsoleHandler(DWORD);
53
#endif
54
#ifdef _MSC_VER
55
#include <Mmsystem.h>
56
#pragma comment(lib, "winmm.lib")
57
#endif
58
59
#define LP_SCANTIME 60
60
61
#ifndef min
62
#define min(a,b) (a>b ? b : a)
63
#define max(a,b) (a<b ? b : a)
64
#endif
65
66
enum workio_commands {
67
WC_GET_WORK,
68
WC_SUBMIT_WORK,
69
};
70
71
struct workio_cmd {
72
enum workio_commands cmd;
73
struct thr_info *thr;
74
union {
75
struct work *work;
76
} u;
77
};
78
79
enum algos {
80
ALGO_KECCAK, /* Keccak (old) */
81
ALGO_KECCAKC, /* Keccak */
82
ALGO_HEAVY, /* Heavy */
83
ALGO_NEOSCRYPT, /* NeoScrypt(128, 2, 1) with Salsa20/20 and ChaCha20/20 */
84
ALGO_QUARK, /* Quark */
85
ALGO_ALLIUM, /* Garlicoin double lyra2 */
86
ALGO_AXIOM, /* Shabal 256 Memohash */
87
ALGO_BASTION,
88
ALGO_BLAKE, /* Blake 256 */
89
ALGO_BLAKECOIN, /* Simplified 8 rounds Blake 256 */
90
ALGO_BLAKE2B,
91
ALGO_BLAKE2S, /* Blake2s */
92
ALGO_BMW, /* BMW 256 */
93
ALGO_C11, /* C11 Chaincoin/Flaxcoin X11 variant */
94
ALGO_CRYPTOLIGHT, /* cryptonight-light (Aeon) */
95
ALGO_CRYPTONIGHT, /* CryptoNight */
96
ALGO_DECRED, /* Decred */
97
ALGO_DMD_GR, /* Diamond */
98
ALGO_DROP, /* Dropcoin */
99
ALGO_FRESH, /* Fresh */
100
ALGO_GEEK,
101
ALGO_GROESTL, /* Groestl */
102
ALGO_JHA,
103
ALGO_LBRY, /* Lbry Sha Ripemd */
104
ALGO_LUFFA, /* Luffa (Joincoin, Doom) */
105
ALGO_LYRA2, /* Lyra2RE */
106
ALGO_LYRA2REV2, /* Lyra2REv2 */
107
ALGO_LYRA2V3, /* Lyra2REv3 (Vertcoin) */
108
ALGO_MINOTAUR, /* Minotaur (Ring) */
109
ALGO_MINOTAURX, /* MinotaurX (LCC, Ring) */
110
ALGO_MYR_GR, /* Myriad Groestl */
111
ALGO_NIST5, /* Nist5 */
112
ALGO_PENTABLAKE, /* Pentablake */
113
ALGO_PHI1612,
114
ALGO_PHI2,
115
ALGO_PLUCK, /* Pluck (Supcoin) */
116
ALGO_QUBIT, /* Qubit */
117
ALGO_RAINFOREST, /* RainForest */
118
ALGO_SCRYPT, /* scrypt */
119
ALGO_SCRYPTJANE, /* Chacha */
120
ALGO_SHAVITE3, /* Shavite3 */
121
ALGO_SHA256D, /* SHA-256d */
122
ALGO_SIA, /* Blake2-B */
123
ALGO_SIB, /* X11 + gost (Sibcoin) */
124
ALGO_SKEIN, /* Skein */
125
ALGO_SKEIN2, /* Double skein (Woodcoin) */
126
ALGO_SONOA,
127
ALGO_S3, /* S3 */
128
ALGO_TIMETRAVEL, /* Timetravel-8 (Machinecoin) */
129
ALGO_BITCORE, /* Timetravel-10 (Bitcore) */
130
ALGO_TRIBUS, /* Denarius jh/keccak/echo */
131
ALGO_VANILLA, /* Vanilla (Blake256 8-rounds - double sha256) */
132
ALGO_VELTOR, /* Skein Shavite Shabal Streebog */
133
ALGO_X11EVO, /* Permuted X11 */
134
ALGO_X11, /* X11 */
135
ALGO_X12,
136
ALGO_X13, /* X13 */
137
ALGO_X14, /* X14 */
138
ALGO_X15, /* X15 */
139
ALGO_X16R,
140
ALGO_X16S,
141
ALGO_X17, /* X17 */
142
ALGO_X20R,
143
ALGO_XEVAN,
144
ALGO_ZR5,
145
ALGO_COUNT
146
};
147
148
static const char *algo_names[] = {
149
"keccak",
150
"keccakc",
151
"heavy",
152
"neoscrypt",
153
"quark",
154
"allium",
155
"axiom",
156
"bastion",
157
"blake",
158
"blakecoin",
159
"blake2b",
160
"blake2s",
161
"bmw",
162
"c11",
163
"cryptolight",
164
"cryptonight",
165
"decred",
166
"dmd-gr",
167
"drop",
168
"fresh",
169
"geek",
170
"groestl",
171
"jha",
172
"lbry",
173
"luffa",
174
"lyra2re",
175
"lyra2rev2",
176
"lyra2v3",
177
"minotaur",
178
"minotaurx",
179
"myr-gr",
180
"nist5",
181
"pentablake",
182
"phi1612",
183
"phi2",
184
"pluck",
185
"qubit",
186
"rainforest",
187
"scrypt",
188
"scrypt-jane",
189
"shavite3",
190
"sha256d",
191
"sia",
192
"sib",
193
"skein",
194
"skein2",
195
"sonoa",
196
"s3",
197
"timetravel",
198
"bitcore",
199
"tribus",
200
"vanilla",
201
"veltor",
202
"x11evo",
203
"x11",
204
"x12",
205
"x13",
206
"x14",
207
"x15",
208
"x16r",
209
"x16s",
210
"x17",
211
"x20r",
212
"xevan",
213
"zr5",
214
"\0"
215
};
216
217
bool opt_debug = false;
218
bool opt_debug_diff = false;
219
bool opt_protocol = false;
220
bool opt_benchmark = false;
221
bool opt_redirect = true;
222
bool opt_showdiff = true;
223
bool opt_extranonce = true;
224
bool want_longpoll = true;
225
bool have_longpoll = false;
226
bool have_gbt = true;
227
bool opt_minotaurx = false; // Flag for MinX on GBT
228
bool allow_getwork = true;
229
bool want_stratum = true;
230
bool have_stratum = false;
231
bool opt_stratum_stats = false;
232
bool allow_mininginfo = true;
233
bool use_syslog = false;
234
bool use_colors = true;
235
static bool opt_background = false;
236
bool opt_quiet = false;
237
int opt_maxlograte = 5;
238
bool opt_randomize = false;
239
static int opt_retries = -1;
240
static int opt_fail_pause = 10;
241
static int opt_time_limit = 0;
242
int opt_timeout = 300;
243
static int opt_scantime = 5;
244
static enum algos opt_algo = ALGO_SCRYPT;
245
static int opt_scrypt_n = 1024;
246
static int opt_pluck_n = 128;
247
static unsigned int opt_nfactor = 6;
248
int opt_n_threads = 0;
249
int64_t opt_affinity = -1L;
250
int opt_priority = 0;
251
int num_cpus;
252
char *rpc_url;
253
char *rpc_userpass;
254
char *rpc_user, *rpc_pass;
255
char *short_url = NULL;
256
static unsigned char pk_script[42] = { 0 };
257
static size_t pk_script_size = 0;
258
static char coinbase_sig[101] = { 0 };
259
char *opt_cert;
260
char *opt_proxy;
261
long opt_proxy_type;
262
struct thr_info *thr_info;
263
int work_thr_id;
264
int longpoll_thr_id = -1;
265
int stratum_thr_id = -1;
266
int api_thr_id = -1;
267
bool stratum_need_reset = false;
268
struct work_restart *work_restart = NULL;
269
struct stratum_ctx stratum;
270
bool jsonrpc_2 = false;
271
char rpc2_id[64] = "";
272
char *rpc2_blob = NULL;
273
size_t rpc2_bloblen = 0;
274
uint32_t rpc2_target = 0;
275
char *rpc2_job_id = NULL;
276
bool aes_ni_supported = false;
277
double opt_diff_factor = 1.0;
278
pthread_mutex_t rpc2_job_lock;
279
pthread_mutex_t rpc2_login_lock;
280
pthread_mutex_t applog_lock;
281
pthread_mutex_t stats_lock;
282
uint32_t zr5_pok = 0;
283
bool use_roots = false;
284
uint32_t solved_count = 0L;
285
uint32_t accepted_count = 0L;
286
uint32_t rejected_count = 0L;
287
double *thr_hashrates;
288
uint64_t global_hashrate = 0;
289
double stratum_diff = 0.;
290
double net_diff = 0.;
291
double net_hashrate = 0.;
292
uint64_t net_blocks = 0;
293
// conditional mining
294
bool conditional_state[MAX_CPUS] = { 0 };
295
double opt_max_temp = 0.0;
296
double opt_max_diff = 0.0;
297
double opt_max_rate = 0.0;
298
299
uint32_t opt_work_size = 0; /* default */
300
char *opt_api_allow = NULL;
301
int opt_api_remote = 0;
302
int opt_api_listen = 4048; /* 0 to disable */
303
304
#ifdef HAVE_GETOPT_LONG
305
#include <getopt.h>
306
#else
307
struct option {
308
const char *name;
309
int has_arg;
310
int *flag;
311
int val;
312
};
313
#endif
314
315
static char const usage[] = "\
316
Usage: " PACKAGE_NAME " [OPTIONS]\n\
317
Options:\n\
318
-a, --algo=ALGO specify the algorithm to use\n\
319
allium Garlicoin double lyra2\n\
320
axiom Shabal-256 MemoHash\n\
321
bitcore Timetravel with 10 algos\n\
322
blake Blake-256 14-rounds (SFR)\n\
323
blakecoin Blake-256 single sha256 merkle\n\
324
blake2b Blake2-B (512)\n\
325
blake2s Blake2-S (256)\n\
326
bmw BMW 256\n\
327
c11/flax C11\n\
328
cryptolight Cryptonight-light\n\
329
cryptonight Monero\n\
330
decred Blake-256 14-rounds 180 bytes\n\
331
dmd-gr Diamond-Groestl\n\
332
drop Dropcoin\n\
333
fresh Fresh\n\
334
geek GeekCash\n\
335
groestl GroestlCoin\n\
336
heavy Heavy\n\
337
jha JHA\n\
338
keccak Keccak (Old and deprecated)\n\
339
keccakc Keccak (CreativeCoin)\n\
340
luffa Luffa\n\
341
lyra2re Lyra2RE\n\
342
lyra2rev2 Lyra2REv2\n\
343
lyra2v3 Lyra2REv3 (Vertcoin)\n\
344
minotaur Minotaur\n\
345
minotaurx MinotaurX\n\
346
myr-gr Myriad-Groestl\n\
347
neoscrypt NeoScrypt(128, 2, 1)\n\
348
nist5 Nist5\n\
349
pluck Pluck:128 (Supcoin)\n\
350
pentablake Pentablake\n\
351
phi LUX initial algo\n\
352
phi2 LUX newer algo\n\
353
quark Quark\n\
354
qubit Qubit\n\
355
rainforest RainForest (256)\n\
356
scrypt scrypt(1024, 1, 1) (default)\n\
357
scrypt:N scrypt(N, 1, 1)\n\
358
scrypt-jane:N (with N factor from 4 to 30)\n\
359
shavite3 Shavite3\n\
360
sha256d SHA-256d\n\
361
sia Blake2-B\n\
362
sib X11 + gost (SibCoin)\n\
363
skein Skein+Sha (Skeincoin)\n\
364
skein2 Double Skein (Woodcoin)\n\
365
sonoa A series of 97 hashes from x17\n\
366
s3 S3\n\
367
timetravel Timetravel (Machinecoin)\n\
368
vanilla Blake-256 8-rounds\n\
369
x11evo Permuted x11\n\
370
x11 X11\n\
371
x12 X12\n\
372
x13 X13\n\
373
x14 X14\n\
374
x15 X15\n\
375
x16r X16R (Raven)\n\
376
x16s X16S (Pigeon)\n\
377
x17 X17\n\
378
x20r X20R\n\
379
xevan Xevan (BitSend)\n\
380
zr5 ZR5\n\
381
-o, --url=URL URL of mining server\n\
382
-O, --userpass=U:P username:password pair for mining server\n\
383
-u, --user=USERNAME username for mining server\n\
384
-p, --pass=PASSWORD password for mining server\n\
385
--cert=FILE certificate for mining server using SSL\n\
386
-x, --proxy=[PROTOCOL://]HOST[:PORT] connect through a proxy\n\
387
-t, --threads=N number of miner threads (default: number of processors)\n\
388
-r, --retries=N number of times to retry if a network call fails\n\
389
(default: retry indefinitely)\n\
390
-R, --retry-pause=N time to pause between retries, in seconds (default: 30)\n\
391
--time-limit=N maximum time [s] to mine before exiting the program.\n\
392
-T, --timeout=N timeout for long poll and stratum (default: 300 seconds)\n\
393
-s, --scantime=N upper bound on time spent scanning current work when\n\
394
long polling is unavailable, in seconds (default: 5)\n\
395
--randomize Randomize scan range start to reduce duplicates\n\
396
-f, --diff-factor Divide req. difficulty by this factor (std is 1.0)\n\
397
-m, --diff-multiplier Multiply difficulty by this factor (std is 1.0)\n\
398
-n, --nfactor neoscrypt N-Factor\n\
399
--coinbase-addr=ADDR payout address for solo mining\n\
400
--coinbase-sig=TEXT data to insert in the coinbase when possible\n\
401
--max-log-rate limit per-core hashrate logs (default: 5s)\n\
402
--no-longpoll disable long polling support\n\
403
--no-getwork disable getwork support\n\
404
--no-gbt disable getblocktemplate support\n\
405
--no-stratum disable X-Stratum support\n\
406
--no-extranonce disable Stratum extranonce support\n\
407
--no-redirect ignore requests to change the URL of the mining server\n\
408
-q, --quiet disable per-thread hashmeter output\n\
409
--no-color disable colored output\n\
410
-D, --debug enable debug output\n\
411
-P, --protocol-dump verbose dump of protocol-level activities\n\
412
--hide-diff Hide submitted block and net difficulty\n"
413
#ifdef HAVE_SYSLOG_H
414
"\
415
-S, --syslog use system log for output messages\n"
416
#endif
417
"\
418
-B, --background run the miner in the background\n\
419
--benchmark run in offline benchmark mode\n\
420
--cputest debug hashes from cpu algorithms\n\
421
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1\n\
422
--cpu-priority set process priority (default: 0 idle, 2 normal to 5 highest)\n\
423
-b, --api-bind IP/Port for the miner API (default: 127.0.0.1:4048)\n\
424
--api-remote Allow remote control\n\
425
--max-temp=N Only mine if cpu temp is less than specified value (linux)\n\
426
--max-rate=N[KMG] Only mine if net hashrate is less than specified value\n\
427
--max-diff=N Only mine if net difficulty is less than specified value\n\
428
-c, --config=FILE load a JSON-format configuration file\n\
429
-V, --version display version information and exit\n\
430
-h, --help display this help text and exit\n\
431
";
432
433
434
static char const short_options[] =
435
#ifdef HAVE_SYSLOG_H
436
"S"
437
#endif
438
"a:b:Bc:CDf:hm:n:p:Px:qr:R:s:t:T:o:u:O:V";
439
440
static struct option const options[] = {
441
{ "algo", 1, NULL, 'a' },
442
{ "api-bind", 1, NULL, 'b' },
443
{ "api-remote", 0, NULL, 1030 },
444
{ "background", 0, NULL, 'B' },
445
{ "benchmark", 0, NULL, 1005 },
446
{ "cputest", 0, NULL, 1006 },
447
{ "cert", 1, NULL, 1001 },
448
{ "coinbase-addr", 1, NULL, 1016 },
449
{ "coinbase-sig", 1, NULL, 1015 },
450
{ "config", 1, NULL, 'c' },
451
{ "cpu-affinity", 1, NULL, 1020 },
452
{ "cpu-priority", 1, NULL, 1021 },
453
{ "no-color", 0, NULL, 1002 },
454
{ "debug", 0, NULL, 'D' },
455
{ "diff-factor", 1, NULL, 'f' },
456
{ "diff", 1, NULL, 'f' }, // deprecated (alias)
457
{ "diff-multiplier", 1, NULL, 'm' },
458
{ "help", 0, NULL, 'h' },
459
{ "nfactor", 1, NULL, 'n' },
460
{ "no-gbt", 0, NULL, 1011 },
461
{ "no-getwork", 0, NULL, 1010 },
462
{ "no-longpoll", 0, NULL, 1003 },
463
{ "no-redirect", 0, NULL, 1009 },
464
{ "no-stratum", 0, NULL, 1007 },
465
{ "no-extranonce", 0, NULL, 1012 },
466
{ "max-temp", 1, NULL, 1060 },
467
{ "max-diff", 1, NULL, 1061 },
468
{ "max-rate", 1, NULL, 1062 },
469
{ "pass", 1, NULL, 'p' },
470
{ "protocol", 0, NULL, 'P' },
471
{ "protocol-dump", 0, NULL, 'P' },
472
{ "proxy", 1, NULL, 'x' },
473
{ "quiet", 0, NULL, 'q' },
474
{ "retries", 1, NULL, 'r' },
475
{ "retry-pause", 1, NULL, 'R' },
476
{ "randomize", 0, NULL, 1024 },
477
{ "scantime", 1, NULL, 's' },
478
{ "show-diff", 0, NULL, 1013 },
479
{ "hide-diff", 0, NULL, 1014 },
480
{ "max-log-rate", 1, NULL, 1019 },
481
#ifdef HAVE_SYSLOG_H
482
{ "syslog", 0, NULL, 'S' },
483
#endif
484
{ "time-limit", 1, NULL, 1008 },
485
{ "threads", 1, NULL, 't' },
486
{ "timeout", 1, NULL, 'T' },
487
{ "url", 1, NULL, 'o' },
488
{ "user", 1, NULL, 'u' },
489
{ "userpass", 1, NULL, 'O' },
490
{ "version", 0, NULL, 'V' },
491
{ 0, 0, 0, 0 }
492
};
493
494
static struct work g_work = {{ 0 }};
495
static time_t g_work_time = 0;
496
static pthread_mutex_t g_work_lock;
497
static bool submit_old = false;
498
static char *lp_id;
499
500
static void workio_cmd_free(struct workio_cmd *wc);
501
502
503
#ifdef __linux /* Linux specific policy and affinity management */
504
#include <sched.h>
505
506
static inline void drop_policy(void)
507
{
508
struct sched_param param;
509
param.sched_priority = 0;
510
#ifdef SCHED_IDLE
511
if (unlikely(sched_setscheduler(0, SCHED_IDLE, &param) == -1))
512
#endif
513
#ifdef SCHED_BATCH
514
sched_setscheduler(0, SCHED_BATCH, &param);
515
#endif
516
}
517
518
#ifdef __BIONIC__
519
#define pthread_setaffinity_np(tid,sz,s) {} /* only do process affinity */
520
#endif
521
522
static void affine_to_cpu_mask(int id, unsigned long mask) {
523
cpu_set_t set;
524
CPU_ZERO(&set);
525
for (uint8_t i = 0; i < num_cpus; i++) {
526
// cpu mask
527
if (mask & (1UL<<i)) { CPU_SET(i, &set); }
528
}
529
if (id == -1) {
530
// process affinity
531
sched_setaffinity(0, sizeof(&set), &set);
532
} else {
533
// thread only
534
pthread_setaffinity_np(thr_info[id].pth, sizeof(&set), &set);
535
}
536
}
537
538
#elif defined(WIN32) /* Windows */
539
static inline void drop_policy(void) { }
540
static void affine_to_cpu_mask(int id, unsigned long mask) {
541
if (id == -1)
542
SetProcessAffinityMask(GetCurrentProcess(), mask);
543
else
544
SetThreadAffinityMask(GetCurrentThread(), mask);
545
}
546
#else
547
static inline void drop_policy(void) { }
548
static void affine_to_cpu_mask(int id, unsigned long mask) { }
549
#endif
550
551
void get_currentalgo(char* buf, int sz)
552
{
553
if (opt_algo == ALGO_SCRYPTJANE)
554
snprintf(buf, sz, "%s:%d", algo_names[opt_algo], opt_scrypt_n);
555
else
556
snprintf(buf, sz, "%s", algo_names[opt_algo]);
557
}
558
559
void proper_exit(int reason)
560
{
561
#ifdef WIN32
562
if (opt_background) {
563
HWND hcon = GetConsoleWindow();
564
if (hcon) {
565
// unhide parent command line windows
566
ShowWindow(hcon, SW_SHOWMINNOACTIVE);
567
}
568
}
569
#endif
570
exit(reason);
571
}
572
573
static inline void work_free(struct work *w)
574
{
575
if (w->txs) free(w->txs);
576
if (w->workid) free(w->workid);
577
if (w->job_id) free(w->job_id);
578
if (w->xnonce2) free(w->xnonce2);
579
}
580
581
static inline void work_copy(struct work *dest, const struct work *src)
582
{
583
memcpy(dest, src, sizeof(struct work));
584
if (src->txs)
585
dest->txs = strdup(src->txs);
586
if (src->workid)
587
dest->workid = strdup(src->workid);
588
if (src->job_id)
589
dest->job_id = strdup(src->job_id);
590
if (src->xnonce2) {
591
dest->xnonce2 = (uchar*) malloc(src->xnonce2_len);
592
memcpy(dest->xnonce2, src->xnonce2, src->xnonce2_len);
593
}
594
}
595
596
/* compute nbits to get the network diff */
597
static void calc_network_diff(struct work *work)
598
{
599
// sample for diff 43.281 : 1c05ea29
600
// todo: endian reversed on longpoll could be zr5 specific...
601
uint32_t nbits = have_longpoll ? work->data[18] : swab32(work->data[18]);
602
if (opt_algo == ALGO_LBRY) nbits = swab32(work->data[26]);
603
if (opt_algo == ALGO_DECRED) nbits = work->data[29];
604
if (opt_algo == ALGO_SIA) nbits = work->data[11]; // unsure if correct
605
uint32_t bits = (nbits & 0xffffff);
606
int16_t shift = (swab32(nbits) & 0xff); // 0x1c = 28
607
608
double d = (double)0x0000ffff / (double)bits;
609
for (int m=shift; m < 29; m++) d *= 256.0;
610
for (int m=29; m < shift; m++) d /= 256.0;
611
if (opt_algo == ALGO_DECRED && shift == 28) d *= 256.0; // testnet
612
if (opt_debug_diff)
613
applog(LOG_DEBUG, "net diff: %f -> shift %u, bits %08x", d, shift, bits);
614
net_diff = d;
615
}
616
617
static bool work_decode(const json_t *val, struct work *work)
618
{
619
int i;
620
int data_size = 128, target_size = sizeof(work->target);
621
int adata_sz = 32, atarget_sz = ARRAY_SIZE(work->target);
622
623
if (opt_algo == ALGO_DROP || opt_algo == ALGO_NEOSCRYPT || opt_algo == ALGO_ZR5) {
624
data_size = 80; target_size = 32;
625
adata_sz = 20;
626
atarget_sz = target_size / sizeof(uint32_t);
627
} else if (opt_algo == ALGO_DECRED) {
628
allow_mininginfo = false;
629
data_size = 192;
630
adata_sz = 180/4;
631
} else if (use_roots) {
632
data_size = 144;
633
adata_sz = 36;
634
}
635
636
if (jsonrpc_2) {
637
return rpc2_job_decode(val, work);
638
}
639
640
if (unlikely(!jobj_binary(val, "data", work->data, data_size))) {
641
applog(LOG_ERR, "JSON invalid data");
642
goto err_out;
643
}
644
if (unlikely(!jobj_binary(val, "target", work->target, target_size))) {
645
applog(LOG_ERR, "JSON invalid target");
646
goto err_out;
647
}
648
649
for (i = 0; i < adata_sz; i++)
650
work->data[i] = le32dec(work->data + i);
651
for (i = 0; i < atarget_sz; i++)
652
work->target[i] = le32dec(work->target + i);
653
654
if ((opt_showdiff || opt_max_diff > 0.) && !allow_mininginfo)
655
calc_network_diff(work);
656
657
work->targetdiff = target_to_diff(work->target);
658
659
// for api stats, on longpoll pools
660
stratum_diff = work->targetdiff;
661
662
if (opt_algo == ALGO_DROP || opt_algo == ALGO_ZR5) {
663
#define POK_BOOL_MASK 0x00008000
664
#define POK_DATA_MASK 0xFFFF0000
665
if (work->data[0] & POK_BOOL_MASK) {
666
applog(LOG_BLUE, "POK received: %08xx", work->data[0]);
667
zr5_pok = work->data[0] & POK_DATA_MASK;
668
}
669
} else if (opt_algo == ALGO_DECRED) {
670
// some random extradata to make the work unique
671
work->data[36] = (rand()*4);
672
work->height = work->data[32];
673
// required for the getwork pools (multicoin.co)
674
if (!have_longpoll && work->height > net_blocks + 1) {
675
char netinfo[64] = { 0 };
676
if (opt_showdiff && net_diff > 0.) {
677
if (net_diff != work->targetdiff)
678
sprintf(netinfo, ", diff %.3f, target %.1f", net_diff, work->targetdiff);
679
else
680
sprintf(netinfo, ", diff %.3f", net_diff);
681
}
682
applog(LOG_BLUE, "%s block %d%s",
683
algo_names[opt_algo], work->height, netinfo);
684
net_blocks = work->height - 1;
685
}
686
} else if (opt_algo == ALGO_PHI2) {
687
if (work->data[0] & (1<<30)) use_roots = true;
688
else for (i = 20; i < 36; i++) {
689
if (work->data[i]) { use_roots = true; break; }
690
}
691
}
692
693
return true;
694
695
err_out:
696
return false;
697
}
698
699
// good alternative for wallet mining, difficulty and net hashrate
700
static const char *info_req =
701
"{\"method\": \"getmininginfo\", \"params\": [], \"id\":8}\r\n";
702
703
static bool get_mininginfo(CURL *curl, struct work *work)
704
{
705
if (have_stratum || have_longpoll || !allow_mininginfo)
706
return false;
707
708
int curl_err = 0;
709
json_t *val = json_rpc_call(curl, rpc_url, rpc_userpass, info_req, &curl_err, 0);
710
711
if (!val && curl_err == -1) {
712
allow_mininginfo = false;
713
if (opt_debug) {
714
applog(LOG_DEBUG, "getmininginfo not supported");
715
}
716
return false;
717
}
718
else {
719
json_t *res = json_object_get(val, "result");
720
// "blocks": 491493 (= current work height - 1)
721
// "difficulty": 0.99607860999999998
722
// "networkhashps": 56475980
723
if (res) {
724
json_t *key = json_object_get(res, "difficulty");
725
if (key) {
726
if (json_is_object(key))
727
key = json_object_get(key, "proof-of-work");
728
if (json_is_real(key))
729
net_diff = json_real_value(key);
730
}
731
key = json_object_get(res, "networkhashps");
732
if (key && json_is_integer(key)) {
733
net_hashrate = (double) json_integer_value(key);
734
}
735
key = json_object_get(res, "blocks");
736
if (key && json_is_integer(key)) {
737
net_blocks = json_integer_value(key);
738
}
739
if (!work->height) {
740
// complete missing data from getwork
741
work->height = (uint32_t) net_blocks + 1;
742
if (work->height > g_work.height) {
743
restart_threads();
744
if (!opt_quiet) {
745
char netinfo[64] = { 0 };
746
char srate[32] = { 0 };
747
sprintf(netinfo, "diff %.2f", net_diff);
748
if (net_hashrate) {
749
format_hashrate(net_hashrate, srate);
750
strcat(netinfo, ", net ");
751
strcat(netinfo, srate);
752
}
753
applog(LOG_BLUE, "%s block %d, %s",
754
algo_names[opt_algo], work->height, netinfo);
755
}
756
}
757
}
758
}
759
}
760
json_decref(val);
761
return true;
762
}
763
764
#define BLOCK_VERSION_CURRENT 3
765
766
static bool gbt_work_decode(const json_t *val, struct work *work)
767
{
768
int i, n;
769
uint32_t version, curtime, bits;
770
uint32_t prevhash[8];
771
uint32_t target[8];
772
int cbtx_size;
773
uchar *cbtx = NULL;
774
int tx_count, tx_size;
775
uchar txc_vi[9];
776
uchar(*merkle_tree)[32] = NULL;
777
bool coinbase_append = false;
778
bool submit_coinbase = false;
779
// Segwit BEGIN
780
//bool version_force = false;
781
//bool version_reduce = false;
782
bool segwit = false;
783
// Segwit END
784
785
json_t *tmp, *txa;
786
bool rc = false;
787
788
// Segwit BEGIN
789
tmp = json_object_get(val, "rules");
790
if (tmp && json_is_array(tmp)) {
791
n = json_array_size(tmp);
792
for (i = 0; i < n; i++) {
793
const char *s = json_string_value(json_array_get(tmp, i));
794
if (!s)
795
continue;
796
if (!strcmp(s, "segwit") || !strcmp(s, "!segwit"))
797
segwit = true;
798
}
799
}
800
// Segwit END
801
802
tmp = json_object_get(val, "mutable");
803
if (tmp && json_is_array(tmp)) {
804
n = (int) json_array_size(tmp);
805
for (i = 0; i < n; i++) {
806
const char *s = json_string_value(json_array_get(tmp, i));
807
if (!s)
808
continue;
809
if (!strcmp(s, "coinbase/append"))
810
coinbase_append = true;
811
else if (!strcmp(s, "submit/coinbase"))
812
submit_coinbase = true;
813
// Segwit BEGIN
814
/*
815
else if (!strcmp(s, "version/force"))
816
version_force = true;
817
else if (!strcmp(s, "version/reduce"))
818
version_reduce = true;
819
*/
820
// Segwit END
821
}
822
}
823
824
tmp = json_object_get(val, "height");
825
if (!tmp || !json_is_integer(tmp)) {
826
applog(LOG_ERR, "JSON invalid height");
827
goto out;
828
}
829
work->height = (int) json_integer_value(tmp);
830
applog(LOG_BLUE, "Current block is %d", work->height);
831
832
tmp = json_object_get(val, "version");
833
if (!tmp || !json_is_integer(tmp)) {
834
applog(LOG_ERR, "JSON invalid version");
835
goto out;
836
}
837
version = (uint32_t) json_integer_value(tmp);
838
839
// Segwit BEGIN
840
/*
841
if ((version & 0xffU) > BLOCK_VERSION_CURRENT) {
842
if (version_reduce) {
843
version = (version & ~0xffU) | BLOCK_VERSION_CURRENT;
844
} else if (have_gbt && allow_getwork && !version_force) {
845
applog(LOG_DEBUG, "Switching to getwork, gbt version %d", version);
846
have_gbt = false;
847
goto out;
848
} else if (!version_force) {
849
applog(LOG_ERR, "Unrecognized block version: %u", version);
850
goto out;
851
}
852
}*/
853
// Segwit END
854
855
if (unlikely(!jobj_binary(val, "previousblockhash", prevhash, sizeof(prevhash)))) {
856
applog(LOG_ERR, "JSON invalid previousblockhash");
857
goto out;
858
}
859
860
tmp = json_object_get(val, "curtime");
861
if (!tmp || !json_is_integer(tmp)) {
862
applog(LOG_ERR, "JSON invalid curtime");
863
goto out;
864
}
865
curtime = (uint32_t) json_integer_value(tmp);
866
867
if (unlikely(!jobj_binary(val, "bits", &bits, sizeof(bits)))) {
868
applog(LOG_ERR, "JSON invalid bits");
869
goto out;
870
}
871
872
/* find count and size of transactions */
873
txa = json_object_get(val, "transactions");
874
if (!txa || !json_is_array(txa)) {
875
applog(LOG_ERR, "JSON invalid transactions");
876
goto out;
877
}
878
tx_count = (int) json_array_size(txa);
879
tx_size = 0;
880
for (i = 0; i < tx_count; i++) {
881
const json_t *tx = json_array_get(txa, i);
882
const char *tx_hex = json_string_value(json_object_get(tx, "data"));
883
if (!tx_hex) {
884
applog(LOG_ERR, "JSON invalid transactions");
885
goto out;
886
}
887
tx_size += (int) (strlen(tx_hex) / 2);
888
}
889
890
/* build coinbase transaction */
891
tmp = json_object_get(val, "coinbasetxn");
892
if (tmp) {
893
const char *cbtx_hex = json_string_value(json_object_get(tmp, "data"));
894
cbtx_size = cbtx_hex ? (int) strlen(cbtx_hex) / 2 : 0;
895
cbtx = (uchar*) malloc(cbtx_size + 100);
896
if (cbtx_size < 60 || !hex2bin(cbtx, cbtx_hex, cbtx_size)) {
897
applog(LOG_ERR, "JSON invalid coinbasetxn");
898
goto out;
899
}
900
} else {
901
int64_t cbvalue;
902
if (!pk_script_size) {
903
if (allow_getwork) {
904
applog(LOG_INFO, "No payout address provided, switching to getwork");
905
have_gbt = false;
906
} else
907
applog(LOG_ERR, "No payout address provided");
908
goto out;
909
}
910
tmp = json_object_get(val, "coinbasevalue");
911
if (!tmp || !json_is_number(tmp)) {
912
applog(LOG_ERR, "JSON invalid coinbasevalue");
913
goto out;
914
}
915
cbvalue = (int64_t) (json_is_integer(tmp) ? json_integer_value(tmp) : json_number_value(tmp));
916
cbtx = (uchar*) malloc(256);
917
le32enc((uint32_t *)cbtx, 1); /* version */
918
cbtx[4] = 1; /* in-counter */
919
memset(cbtx+5, 0x00, 32); /* prev txout hash */
920
le32enc((uint32_t *)(cbtx+37), 0xffffffff); /* prev txout index */
921
cbtx_size = 43;
922
/* BIP 34: height in coinbase */
923
for (n = work->height; n; n >>= 8)
924
cbtx[cbtx_size++] = n & 0xff;
925
/* If the last byte pushed is >= 0x80, then we need to add
926
another zero byte to signal that the block height is a
927
positive number. */
928
if (cbtx[cbtx_size - 1] & 0x80)
929
cbtx[cbtx_size++] = 0;
930
cbtx[42] = cbtx_size - 43;
931
cbtx[41] = cbtx_size - 42; /* scriptsig length */
932
le32enc((uint32_t *)(cbtx+cbtx_size), 0xffffffff); /* sequence */
933
cbtx_size += 4;
934
// Segwit BEGIN
935
//cbtx[cbtx_size++] = 1; /* out-counter */
936
cbtx[cbtx_size++] = segwit ? 2 : 1; /* out-counter */
937
// Segwit END
938
le32enc((uint32_t *)(cbtx+cbtx_size), (uint32_t)cbvalue); /* value */
939
le32enc((uint32_t *)(cbtx+cbtx_size+4), cbvalue >> 32);
940
cbtx_size += 8;
941
cbtx[cbtx_size++] = (uint8_t) pk_script_size; /* txout-script length */
942
memcpy(cbtx+cbtx_size, pk_script, pk_script_size);
943
cbtx_size += (int) pk_script_size;
944
// Segwit BEGIN
945
if (segwit) {
946
unsigned char (*wtree)[32] = calloc(tx_count + 2, 32);
947
memset(cbtx+cbtx_size, 0, 8); /* value */
948
cbtx_size += 8;
949
cbtx[cbtx_size++] = 38; /* txout-script length */
950
cbtx[cbtx_size++] = 0x6a; /* txout-script */
951
cbtx[cbtx_size++] = 0x24;
952
cbtx[cbtx_size++] = 0xaa;
953
cbtx[cbtx_size++] = 0x21;
954
cbtx[cbtx_size++] = 0xa9;
955
cbtx[cbtx_size++] = 0xed;
956
for (i = 0; i < tx_count; i++) {
957
const json_t *tx = json_array_get(txa, i);
958
const json_t *hash = json_object_get(tx, "hash");
959
if (!hash || !hex2bin(wtree[1+i], json_string_value(hash), 32)) {
960
applog(LOG_ERR, "JSON invalid transaction hash");
961
free(wtree);
962
goto out;
963
}
964
memrev(wtree[1+i], 32);
965
}
966
n = tx_count + 1;
967
while (n > 1) {
968
if (n % 2)
969
memcpy(wtree[n], wtree[n-1], 32);
970
n = (n + 1) / 2;
971
for (i = 0; i < n; i++)
972
sha256d(wtree[i], wtree[2*i], 64);
973
}
974
memset(wtree[1], 0, 32); /* witness reserved value = 0 */
975
sha256d(cbtx+cbtx_size, wtree[0], 64);
976
cbtx_size += 32;
977
free(wtree);
978
}
979
// Segwit END
980
le32enc((uint32_t *)(cbtx+cbtx_size), 0); /* lock time */
981
cbtx_size += 4;
982
coinbase_append = true;
983
}
984
if (coinbase_append) {
985
unsigned char xsig[100];
986
int xsig_len = 0;
987
if (*coinbase_sig) {
988
n = (int) strlen(coinbase_sig);
989
if (cbtx[41] + xsig_len + n <= 100) {
990
memcpy(xsig+xsig_len, coinbase_sig, n);
991
xsig_len += n;
992
} else {
993
applog(LOG_WARNING, "Signature does not fit in coinbase, skipping");
994
}
995
}
996
tmp = json_object_get(val, "coinbaseaux");
997
if (tmp && json_is_object(tmp)) {
998
void *iter = json_object_iter(tmp);
999
while (iter) {
1000
unsigned char buf[100];
1001
const char *s = json_string_value(json_object_iter_value(iter));
1002
n = s ? (int) (strlen(s) / 2) : 0;
1003
if (!s || n > 100 || !hex2bin(buf, s, n)) {
1004
applog(LOG_ERR, "JSON invalid coinbaseaux");
1005
break;
1006
}
1007
if (cbtx[41] + xsig_len + n <= 100) {
1008
memcpy(xsig+xsig_len, buf, n);
1009
xsig_len += n;
1010
}
1011
iter = json_object_iter_next(tmp, iter);
1012
}
1013
}
1014
if (xsig_len) {
1015
unsigned char *ssig_end = cbtx + 42 + cbtx[41];
1016
int push_len = cbtx[41] + xsig_len < 76 ? 1 :
1017
cbtx[41] + 2 + xsig_len > 100 ? 0 : 2;
1018
n = xsig_len + push_len;
1019
memmove(ssig_end + n, ssig_end, cbtx_size - 42 - cbtx[41]);
1020
cbtx[41] += n;
1021
if (push_len == 2)
1022
*(ssig_end++) = 0x4c; /* OP_PUSHDATA1 */
1023
if (push_len)
1024
*(ssig_end++) = xsig_len;
1025
memcpy(ssig_end, xsig, xsig_len);
1026
cbtx_size += n;
1027
}
1028
}
1029
1030
n = varint_encode(txc_vi, 1 + tx_count);
1031
work->txs = (char*) malloc(2 * (n + cbtx_size + tx_size) + 1);
1032
bin2hex(work->txs, txc_vi, n);
1033
bin2hex(work->txs + 2*n, cbtx, cbtx_size);
1034
1035
/* generate merkle root */
1036
merkle_tree = (uchar(*)[32]) calloc(((1 + tx_count + 1) & ~1), 32);
1037
sha256d(merkle_tree[0], cbtx, cbtx_size);
1038
for (i = 0; i < tx_count; i++) {
1039
tmp = json_array_get(txa, i);
1040
const char *tx_hex = json_string_value(json_object_get(tmp, "data"));
1041
const int tx_size = tx_hex ? (int) (strlen(tx_hex) / 2) : 0;
1042
// Segwit BEGIN
1043
/*
1044
unsigned char *tx = (uchar*) malloc(tx_size);
1045
if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) {
1046
applog(LOG_ERR, "JSON invalid transactions");
1047
free(tx);
1048
goto out;
1049
}
1050
sha256d(merkle_tree[1 + i], tx, tx_size);
1051
*/
1052
if (segwit) {
1053
const char *txid = json_string_value(json_object_get(tmp, "txid"));
1054
if (!txid || !hex2bin(merkle_tree[1 + i], txid, 32)) {
1055
applog(LOG_ERR, "JSON invalid transaction txid");
1056
goto out;
1057
}
1058
memrev(merkle_tree[1 + i], 32);
1059
} else {
1060
unsigned char *tx = malloc(tx_size);
1061
if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) {
1062
applog(LOG_ERR, "JSON invalid transactions");
1063
free(tx);
1064
goto out;
1065
}
1066
sha256d(merkle_tree[1 + i], tx, tx_size);
1067
free(tx);
1068
}
1069
// Segwit END
1070
if (!submit_coinbase)
1071
strcat(work->txs, tx_hex);
1072
}
1073
n = 1 + tx_count;
1074
while (n > 1) {
1075
if (n % 2) {
1076
memcpy(merkle_tree[n], merkle_tree[n-1], 32);
1077
++n;
1078
}
1079
n /= 2;
1080
for (i = 0; i < n; i++)
1081
sha256d(merkle_tree[i], merkle_tree[2*i], 64);
1082
}
1083
1084
/* assemble block header */
1085
work->data[0] = swab32(version);
1086
for (i = 0; i < 8; i++)
1087
work->data[8 - i] = le32dec(prevhash + i);
1088
for (i = 0; i < 8; i++)
1089
work->data[9 + i] = be32dec((uint32_t *)merkle_tree[0] + i);
1090
work->data[17] = swab32(curtime);
1091
work->data[18] = le32dec(&bits);
1092
memset(work->data + 19, 0x00, 52);
1093
1094
work->data[20] = 0x80000000;
1095
work->data[31] = 0x00000280;
1096
1097
if (unlikely(!jobj_binary(val, "target", target, sizeof(target)))) {
1098
applog(LOG_ERR, "JSON invalid target");
1099
goto out;
1100
}
1101
for (i = 0; i < ARRAY_SIZE(work->target); i++)
1102
work->target[7 - i] = be32dec(target + i);
1103
1104
tmp = json_object_get(val, "workid");
1105
if (tmp) {
1106
if (!json_is_string(tmp)) {
1107
applog(LOG_ERR, "JSON invalid workid");
1108
goto out;
1109
}
1110
work->workid = strdup(json_string_value(tmp));
1111
}
1112
1113
rc = true;
1114
out:
1115
/* Long polling */
1116
tmp = json_object_get(val, "longpollid");
1117
if (want_longpoll && json_is_string(tmp)) {
1118
free(lp_id);
1119
lp_id = strdup(json_string_value(tmp));
1120
if (!have_longpoll) {
1121
char *lp_uri;
1122
tmp = json_object_get(val, "longpolluri");
1123
lp_uri = json_is_string(tmp) ? strdup(json_string_value(tmp)) : rpc_url;
1124
have_longpoll = true;
1125
tq_push(thr_info[longpoll_thr_id].q, lp_uri);
1126
}
1127
}
1128
1129
free(merkle_tree);
1130
free(cbtx);
1131
return rc;
1132
}
1133
1134
#define YES "yes!"
1135
#define YAY "yay!!!"
1136
#define BOO "booooo"
1137
1138
static int share_result(int result, struct work *work, const char *reason)
1139
{
1140
const char *flag;
1141
char suppl[32] = { 0 };
1142
char s[345];
1143
double hashrate;
1144
double sharediff = work ? work->sharediff : stratum.sharediff;
1145
int i;
1146
1147
hashrate = 0.;
1148
pthread_mutex_lock(&stats_lock);
1149
for (i = 0; i < opt_n_threads; i++)
1150
hashrate += thr_hashrates[i];
1151
result ? accepted_count++ : rejected_count++;
1152
pthread_mutex_unlock(&stats_lock);
1153
1154
global_hashrate = (uint64_t) hashrate;
1155
1156
if (!net_diff || sharediff < net_diff) {
1157
flag = use_colors ?
1158
(result ? CL_GRN YES : CL_RED BOO)
1159
: (result ? "(" YES ")" : "(" BOO ")");
1160
} else {
1161
solved_count++;
1162
flag = use_colors ?
1163
(result ? CL_GRN YAY : CL_RED BOO)
1164
: (result ? "(" YAY ")" : "(" BOO ")");
1165
}
1166
1167
if (opt_showdiff)
1168
sprintf(suppl, "diff %.3f", sharediff);
1169
else // accepted percent
1170
sprintf(suppl, "%.2f%%", 100. * accepted_count / (accepted_count + rejected_count));
1171
1172
switch (opt_algo) {
1173
case ALGO_AXIOM:
1174
case ALGO_CRYPTOLIGHT:
1175
case ALGO_CRYPTONIGHT:
1176
case ALGO_PLUCK:
1177
case ALGO_SCRYPTJANE:
1178
sprintf(s, hashrate >= 1e6 ? "%.0f" : "%.2f", hashrate);
1179
applog(LOG_NOTICE, "accepted: %lu/%lu (%s), %s H/s %s",
1180
accepted_count, accepted_count + rejected_count,
1181
suppl, s, flag);
1182
break;
1183
default:
1184
sprintf(s, hashrate >= 1e6 ? "%.0f" : "%.2f", hashrate / 1000.0);
1185
applog(LOG_NOTICE, "accepted: %lu/%lu (%s), %s kH/s %s",
1186
accepted_count, accepted_count + rejected_count,
1187
suppl, s, flag);
1188
break;
1189
}
1190
1191
if (reason) {
1192
applog(LOG_WARNING, "reject reason: %s", reason);
1193
if (0 && strncmp(reason, "low difficulty share", 20) == 0) {
1194
opt_diff_factor = (opt_diff_factor * 2.0) / 3.0;
1195
applog(LOG_WARNING, "factor reduced to : %0.2f", opt_diff_factor);
1196
return 0;
1197
}
1198
}
1199
return 1;
1200
}
1201
1202
static bool submit_upstream_work(CURL *curl, struct work *work)
1203
{
1204
json_t *val, *res, *reason;
1205
char s[JSON_BUF_LEN];
1206
int i;
1207
bool rc = false;
1208
1209
/* pass if the previous hash is not the current previous hash */
1210
if (opt_algo != ALGO_SIA && !submit_old && memcmp(&work->data[1], &g_work.data[1], 32)) {
1211
if (opt_debug)
1212
applog(LOG_DEBUG, "DEBUG: stale work detected, discarding");
1213
return true;
1214
}
1215
1216
if (!have_stratum && allow_mininginfo) {
1217
struct work wheight;
1218
get_mininginfo(curl, &wheight);
1219
if (work->height && work->height <= net_blocks) {
1220
if (opt_debug)
1221
applog(LOG_WARNING, "block %u was already solved", work->height);
1222
return true;
1223
}
1224
}
1225
1226
if (have_stratum) {
1227
uint32_t ntime, nonce;
1228
char ntimestr[9], noncestr[9];
1229
1230
if (jsonrpc_2) {
1231
uchar hash[32];
1232
1233
bin2hex(noncestr, (const unsigned char *)work->data + 39, 4);
1234
switch(opt_algo) {
1235
case ALGO_CRYPTOLIGHT:
1236
cryptolight_hash(hash, work->data);
1237
break;
1238
case ALGO_CRYPTONIGHT:
1239
cryptonight_hash(hash, work->data);
1240
default:
1241
break;
1242
}
1243
char *hashhex = abin2hex(hash, 32);
1244
snprintf(s, JSON_BUF_LEN,
1245
"{\"method\": \"submit\", \"params\": {\"id\": \"%s\", \"job_id\": \"%s\", \"nonce\": \"%s\", \"result\": \"%s\"}, \"id\":4}\r\n",
1246
rpc2_id, work->job_id, noncestr, hashhex);
1247
free(hashhex);
1248
} else {
1249
char *xnonce2str;
1250
1251
switch (opt_algo) {
1252
case ALGO_DECRED:
1253
/* reversed */
1254
be32enc(&ntime, work->data[34]);
1255
be32enc(&nonce, work->data[35]);
1256
break;
1257
case ALGO_LBRY:
1258
le32enc(&ntime, work->data[25]);
1259
le32enc(&nonce, work->data[27]);
1260
break;
1261
case ALGO_DROP:
1262
case ALGO_NEOSCRYPT:
1263
case ALGO_ZR5:
1264
/* reversed */
1265
be32enc(&ntime, work->data[17]);
1266
be32enc(&nonce, work->data[19]);
1267
break;
1268
case ALGO_SIA:
1269
/* reversed */
1270
be32enc(&ntime, work->data[10]);
1271
be32enc(&nonce, work->data[8]);
1272
break;
1273
default:
1274
le32enc(&ntime, work->data[17]);
1275
le32enc(&nonce, work->data[19]);
1276
}
1277
1278
bin2hex(ntimestr, (const unsigned char *)(&ntime), 4);
1279
bin2hex(noncestr, (const unsigned char *)(&nonce), 4);
1280
if (opt_algo == ALGO_DECRED) {
1281
xnonce2str = abin2hex((unsigned char*)(&work->data[36]), stratum.xnonce1_size);
1282
} else if (opt_algo == ALGO_SIA) {
1283
uint16_t high_nonce = swab32(work->data[9]) >> 16;
1284
xnonce2str = abin2hex((unsigned char*)(&high_nonce), 2);
1285
} else {
1286
xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
1287
}
1288
snprintf(s, JSON_BUF_LEN,
1289
"{\"method\": \"mining.submit\", \"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\":4}",
1290
rpc_user, work->job_id, xnonce2str, ntimestr, noncestr);
1291
free(xnonce2str);
1292
}
1293
1294
// store to keep/display solved blocs (work struct not linked on accept notification)
1295
stratum.sharediff = work->sharediff;
1296
1297
if (unlikely(!stratum_send_line(&stratum, s))) {
1298
applog(LOG_ERR, "submit_upstream_work stratum_send_line failed");
1299
goto out;
1300
}
1301
1302
} else if (work->txs) { /* gbt */
1303
1304
char data_str[2 * sizeof(work->data) + 1];
1305
char *req;
1306
1307
for (i = 0; i < ARRAY_SIZE(work->data); i++)
1308
be32enc(work->data + i, work->data[i]);
1309
bin2hex(data_str, (unsigned char *)work->data, 80);
1310
if (work->workid) {
1311
char *params;
1312
val = json_object();
1313
json_object_set_new(val, "workid", json_string(work->workid));
1314
params = json_dumps(val, 0);
1315
json_decref(val);
1316
req = (char*) malloc(128 + 2 * 80 + strlen(work->txs) + strlen(params));
1317
sprintf(req,
1318
"{\"method\": \"submitblock\", \"params\": [\"%s%s\", %s], \"id\":4}\r\n",
1319
data_str, work->txs, params);
1320
free(params);
1321
} else {
1322
req = (char*) malloc(128 + 2 * 80 + strlen(work->txs));
1323
sprintf(req,
1324
"{\"method\": \"submitblock\", \"params\": [\"%s%s\"], \"id\":4}\r\n",
1325
data_str, work->txs);
1326
}
1327
1328
val = json_rpc_call(curl, rpc_url, rpc_userpass, req, NULL, 0);
1329
free(req);
1330
if (unlikely(!val)) {
1331
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
1332
goto out;
1333
}
1334
1335
res = json_object_get(val, "result");
1336
if (json_is_object(res)) {
1337
char *res_str;
1338
bool sumres = false;
1339
void *iter = json_object_iter(res);
1340
while (iter) {
1341
if (json_is_null(json_object_iter_value(iter))) {
1342
sumres = true;
1343
break;
1344
}
1345
iter = json_object_iter_next(res, iter);
1346
}
1347
res_str = json_dumps(res, 0);
1348
share_result(sumres, work, res_str);
1349
free(res_str);
1350
} else
1351
share_result(json_is_null(res), work, json_string_value(res));
1352
1353
json_decref(val);
1354
1355
} else {
1356
1357
char* gw_str = NULL;
1358
int data_size = 128;
1359
int adata_sz;
1360
1361
if (jsonrpc_2) {
1362
char noncestr[9];
1363
uchar hash[32];
1364
char *hashhex;
1365
1366
bin2hex(noncestr, (const unsigned char *)work->data + 39, 4);
1367
1368
switch(opt_algo) {
1369
case ALGO_CRYPTOLIGHT:
1370
cryptolight_hash(hash, work->data);
1371
break;
1372
case ALGO_CRYPTONIGHT:
1373
cryptonight_hash(hash, work->data);
1374
default:
1375
break;
1376
}
1377
hashhex = abin2hex(&hash[0], 32);
1378
snprintf(s, JSON_BUF_LEN,
1379
"{\"method\": \"submit\", \"params\": "
1380
"{\"id\": \"%s\", \"job_id\": \"%s\", \"nonce\": \"%s\", \"result\": \"%s\"},"
1381
"\"id\":4}\r\n",
1382
rpc2_id, work->job_id, noncestr, hashhex);
1383
free(hashhex);
1384
1385
/* issue JSON-RPC request */
1386
val = json_rpc2_call(curl, rpc_url, rpc_userpass, s, NULL, 0);
1387
if (unlikely(!val)) {
1388
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
1389
goto out;
1390
}
1391
res = json_object_get(val, "result");
1392
json_t *status = json_object_get(res, "status");
1393
bool valid = !strcmp(status ? json_string_value(status) : "", "OK");
1394
if (valid)
1395
share_result(valid, work, NULL);
1396
else {
1397
json_t *err = json_object_get(res, "error");
1398
const char *sreason = json_string_value(json_object_get(err, "message"));
1399
share_result(valid, work, sreason);
1400
if (!strcasecmp("Invalid job id", sreason)) {
1401
work_free(work);
1402
work_copy(work, &g_work);
1403
g_work_time = 0;
1404
restart_threads();
1405
}
1406
}
1407
json_decref(val);
1408
return true;
1409
1410
} else if (opt_algo == ALGO_DROP || opt_algo == ALGO_NEOSCRYPT || opt_algo == ALGO_ZR5) {
1411
/* different data size */
1412
data_size = 80;
1413
} else if (opt_algo == ALGO_DECRED) {
1414
/* bigger data size : 180 + terminal hash ending */
1415
data_size = 192;
1416
} else if (opt_algo == ALGO_PHI2 && use_roots) {
1417
data_size = 144;
1418
}
1419
1420
adata_sz = data_size / sizeof(uint32_t);
1421
if (opt_algo == ALGO_DECRED) adata_sz = 180 / 4; // dont touch the end tag
1422
1423
/* build hex string */
1424
for (i = 0; i < adata_sz; i++)
1425
le32enc(&work->data[i], work->data[i]);
1426
1427
gw_str = abin2hex((uchar*)work->data, data_size);
1428
1429
if (unlikely(!gw_str)) {
1430
applog(LOG_ERR, "submit_upstream_work OOM");
1431
return false;
1432
}
1433
1434
//applog(LOG_WARNING, gw_str);
1435
1436
/* build JSON-RPC request */
1437
snprintf(s, JSON_BUF_LEN,
1438
"{\"method\": \"getwork\", \"params\": [\"%s\"], \"id\":4}\r\n", gw_str);
1439
free(gw_str);
1440
1441
/* issue JSON-RPC request */
1442
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, NULL, 0);
1443
if (unlikely(!val)) {
1444
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
1445
goto out;
1446
}
1447
res = json_object_get(val, "result");
1448
reason = json_object_get(val, "reject-reason");
1449
share_result(json_is_true(res), work, reason ? json_string_value(reason) : NULL);
1450
1451
json_decref(val);
1452
}
1453
1454
rc = true;
1455
1456
out:
1457
return rc;
1458
}
1459
1460
static const char *getwork_req =
1461
"{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
1462
1463
#define GBT_CAPABILITIES "[\"coinbasetxn\", \"coinbasevalue\", \"longpoll\", \"workid\"]"
1464
// Segwit BEGIN
1465
/*
1466
static const char *gbt_req =
1467
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
1468
GBT_CAPABILITIES "}], \"id\":0}\r\n";
1469
static const char *gbt_lp_req =
1470
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
1471
GBT_CAPABILITIES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
1472
*/
1473
#define GBT_RULES "[\"segwit\"]"
1474
static const char *gbt_req =
1475
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
1476
GBT_CAPABILITIES ", \"rules\": " GBT_RULES "}], \"id\":0}\r\n";
1477
static const char *gbt_lp_req =
1478
"{\"method\": \"getblocktemplate\", \"params\": [{\"capabilities\": "
1479
GBT_CAPABILITIES ", \"rules\": " GBT_RULES ", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
1480
// Segwit END
1481
// Parameters for MinX BlockTemplate BEGIN
1482
#define MINX_PARAMS "\"powalgo\": \"minotaurx\""
1483
static const char *gbt_req_minx = "{\"method\": \"getblocktemplate\", \"params\": [{"MINX_PARAMS", \"capabilities\": "GBT_CAPABILITIES", \"rules\": "GBT_RULES"}], \"id\":0}\r\n";
1484
static const char *gbt_lp_req_minx = "{\"method\": \"getblocktemplate\", \"params\": [{"MINX_PARAMS", \"capabilities\": "GBT_CAPABILITIES", \"rules\": "GBT_RULES", \"longpollid\": \"%s\"}], \"id\":0}\r\n";
1485
// Parameters for MinX BlockTemplate END
1486
1487
static bool get_upstream_work(CURL *curl, struct work *work)
1488
{
1489
json_t *val;
1490
int err;
1491
bool rc;
1492
struct timeval tv_start, tv_end, diff;
1493
1494
start:
1495
gettimeofday(&tv_start, NULL);
1496
1497
if (jsonrpc_2) {
1498
char s[128];
1499
snprintf(s, 128, "{\"method\": \"getjob\", \"params\": {\"id\": \"%s\"}, \"id\":1}\r\n", rpc2_id);
1500
val = json_rpc2_call(curl, rpc_url, rpc_userpass, s, NULL, 0);
1501
} else {
1502
// Parameters for MinX BlockTemplate BEGIN
1503
/*
1504
val = json_rpc_call(curl, rpc_url, rpc_userpass,
1505
have_gbt ? gbt_req : getwork_req,
1506
&err, have_gbt ? JSON_RPC_QUIET_404 : 0);
1507
*/
1508
if(!opt_minotaurx) {
1509
val = json_rpc_call(curl, rpc_url, rpc_userpass, have_gbt ? gbt_req : getwork_req, &err, have_gbt ? JSON_RPC_QUIET_404 : 0);
1510
} else {
1511
val = json_rpc_call(curl, rpc_url, rpc_userpass, have_gbt ? gbt_req_minx : getwork_req, &err, have_gbt ? JSON_RPC_QUIET_404 : 0);
1512
}
1513
// Parameters for MinX BlockTemplate BEGIN
1514
}
1515
gettimeofday(&tv_end, NULL);
1516
1517
if (have_stratum) {
1518
if (val)
1519
json_decref(val);
1520
return true;
1521
}
1522
1523
if (!have_gbt && !allow_getwork) {
1524
applog(LOG_ERR, "No usable protocol");
1525
if (val)
1526
json_decref(val);
1527
return false;
1528
}
1529
1530
if (have_gbt && allow_getwork && !val && err == CURLE_OK) {
1531
applog(LOG_NOTICE, "getblocktemplate failed, falling back to getwork");
1532
have_gbt = false;
1533
goto start;
1534
}
1535
1536
if (!val)
1537
return false;
1538
1539
if (have_gbt) {
1540
rc = gbt_work_decode(json_object_get(val, "result"), work);
1541
if (!have_gbt) {
1542
json_decref(val);
1543
goto start;
1544
}
1545
} else {
1546
rc = work_decode(json_object_get(val, "result"), work);
1547
}
1548
1549
if (opt_protocol && rc) {
1550
timeval_subtract(&diff, &tv_end, &tv_start);
1551
applog(LOG_DEBUG, "got new work in %.2f ms",
1552
(1000.0 * diff.tv_sec) + (0.001 * diff.tv_usec));
1553
}
1554
1555
json_decref(val);
1556
1557
// store work height in solo
1558
get_mininginfo(curl, work);
1559
1560
return rc;
1561
}
1562
1563
static void workio_cmd_free(struct workio_cmd *wc)
1564
{
1565
if (!wc)
1566
return;
1567
1568
switch (wc->cmd) {
1569
case WC_SUBMIT_WORK:
1570
work_free(wc->u.work);
1571
free(wc->u.work);
1572
break;
1573
default: /* do nothing */
1574
break;
1575
}
1576
1577
memset(wc, 0, sizeof(*wc)); /* poison */
1578
free(wc);
1579
}
1580
1581
static bool workio_get_work(struct workio_cmd *wc, CURL *curl)
1582
{
1583
struct work *ret_work;
1584
int failures = 0;
1585
1586
ret_work = (struct work*) calloc(1, sizeof(*ret_work));
1587
if (!ret_work)
1588
return false;
1589
1590
/* obtain new work from bitcoin via JSON-RPC */
1591
while (!get_upstream_work(curl, ret_work)) {
1592
if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
1593
applog(LOG_ERR, "json_rpc_call failed, terminating workio thread");
1594
free(ret_work);
1595
return false;
1596
}
1597
1598
/* pause, then restart work-request loop */
1599
applog(LOG_ERR, "json_rpc_call failed, retry after %d seconds",
1600
opt_fail_pause);
1601
sleep(opt_fail_pause);
1602
}
1603
1604
/* send work to requesting thread */
1605
if (!tq_push(wc->thr->q, ret_work))
1606
free(ret_work);
1607
1608
return true;
1609
}
1610
1611
static bool workio_submit_work(struct workio_cmd *wc, CURL *curl)
1612
{
1613
int failures = 0;
1614
1615
/* submit solution to bitcoin via JSON-RPC */
1616
while (!submit_upstream_work(curl, wc->u.work)) {
1617
if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
1618
applog(LOG_ERR, "...terminating workio thread");
1619
return false;
1620
}
1621
1622
/* pause, then restart work-request loop */
1623
if (!opt_benchmark)
1624
applog(LOG_ERR, "...retry after %d seconds", opt_fail_pause);
1625
sleep(opt_fail_pause);
1626
}
1627
1628
return true;
1629
}
1630
1631
bool rpc2_login(CURL *curl)
1632
{
1633
json_t *val;
1634
bool rc = false;
1635
struct timeval tv_start, tv_end, diff;
1636
char s[JSON_BUF_LEN];
1637
1638
if (!jsonrpc_2)
1639
return false;
1640
1641
snprintf(s, JSON_BUF_LEN, "{\"method\": \"login\", \"params\": {"
1642
"\"login\": \"%s\", \"pass\": \"%s\", \"agent\": \"%s\"}, \"id\": 1}",
1643
rpc_user, rpc_pass, USER_AGENT);
1644
1645
gettimeofday(&tv_start, NULL);
1646
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, NULL, 0);
1647
gettimeofday(&tv_end, NULL);
1648
1649
if (!val)
1650
goto end;
1651
1652
// applog(LOG_DEBUG, "JSON value: %s", json_dumps(val, 0));
1653
1654
rc = rpc2_login_decode(val);
1655
1656
json_t *result = json_object_get(val, "result");
1657
1658
if (!result)
1659
goto end;
1660
1661
json_t *job = json_object_get(result, "job");
1662
if (!rpc2_job_decode(job, &g_work)) {
1663
goto end;
1664
}
1665
1666
if (opt_debug && rc) {
1667
timeval_subtract(&diff, &tv_end, &tv_start);
1668
applog(LOG_DEBUG, "DEBUG: authenticated in %d ms",
1669
diff.tv_sec * 1000 + diff.tv_usec / 1000);
1670
}
1671
1672
json_decref(val);
1673
end:
1674
return rc;
1675
}
1676
1677
bool rpc2_workio_login(CURL *curl)
1678
{
1679
int failures = 0;
1680
if (opt_benchmark)
1681
return true;
1682
/* submit solution to bitcoin via JSON-RPC */
1683
pthread_mutex_lock(&rpc2_login_lock);
1684
while (!rpc2_login(curl)) {
1685
if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
1686
applog(LOG_ERR, "...terminating workio thread");
1687
pthread_mutex_unlock(&rpc2_login_lock);
1688
return false;
1689
}
1690
1691
/* pause, then restart work-request loop */
1692
if (!opt_benchmark)
1693
applog(LOG_ERR, "...retry after %d seconds", opt_fail_pause);
1694
sleep(opt_fail_pause);
1695
pthread_mutex_unlock(&rpc2_login_lock);
1696
pthread_mutex_lock(&rpc2_login_lock);
1697
}
1698
pthread_mutex_unlock(&rpc2_login_lock);
1699
1700
return true;
1701
}
1702
1703
static void *workio_thread(void *userdata)
1704
{
1705
struct thr_info *mythr = (struct thr_info *) userdata;
1706
CURL *curl;
1707
bool ok = true;
1708
1709
curl = curl_easy_init();
1710
if (unlikely(!curl)) {
1711
applog(LOG_ERR, "CURL initialization failed");
1712
return NULL;
1713
}
1714
1715
if(jsonrpc_2 && !have_stratum) {
1716
ok = rpc2_workio_login(curl);
1717
}
1718
1719
while (ok) {
1720
struct workio_cmd *wc;
1721
1722
/* wait for workio_cmd sent to us, on our queue */
1723
wc = (struct workio_cmd *) tq_pop(mythr->q, NULL);
1724
if (!wc) {
1725
ok = false;
1726
break;
1727
}
1728
1729
/* process workio_cmd */
1730
switch (wc->cmd) {
1731
case WC_GET_WORK:
1732
ok = workio_get_work(wc, curl);
1733
break;
1734
case WC_SUBMIT_WORK:
1735
ok = workio_submit_work(wc, curl);
1736
break;
1737
1738
default: /* should never happen */
1739
ok = false;
1740
break;
1741
}
1742
1743
workio_cmd_free(wc);
1744
}
1745
1746
tq_freeze(mythr->q);
1747
curl_easy_cleanup(curl);
1748
1749
return NULL;
1750
}
1751
1752
static bool get_work(struct thr_info *thr, struct work *work)
1753
{
1754
struct workio_cmd *wc;
1755
struct work *work_heap;
1756
1757
if (opt_benchmark) {
1758
uint32_t ts = (uint32_t) time(NULL);
1759
for (int n=0; n<74; n++) ((char*)work->data)[n] = n;
1760
//memset(work->data, 0x55, 76);
1761
work->data[17] = swab32(ts);
1762
memset(work->data + 19, 0x00, 52);
1763
if (opt_algo == ALGO_DECRED) {
1764
memset(&work->data[35], 0x00, 52);
1765
} else {
1766
work->data[20] = 0x80000000;
1767
work->data[31] = 0x00000280;
1768
}
1769
memset(work->target, 0x00, sizeof(work->target));
1770
return true;
1771
}
1772
1773
/* fill out work request message */
1774
wc = (struct workio_cmd *) calloc(1, sizeof(*wc));
1775
if (!wc)
1776
return false;
1777
1778
wc->cmd = WC_GET_WORK;
1779
wc->thr = thr;
1780
1781
/* send work request to workio thread */
1782
if (!tq_push(thr_info[work_thr_id].q, wc)) {
1783
workio_cmd_free(wc);
1784
return false;
1785
}
1786
1787
/* wait for response, a unit of work */
1788
work_heap = (struct work*) tq_pop(thr->q, NULL);
1789
if (!work_heap)
1790
return false;
1791
1792
/* copy returned work into storage provided by caller */
1793
memcpy(work, work_heap, sizeof(*work));
1794
free(work_heap);
1795
1796
return true;
1797
}
1798
1799
static bool submit_work(struct thr_info *thr, const struct work *work_in)
1800
{
1801
struct workio_cmd *wc;
1802
1803
/* fill out work request message */
1804
wc = (struct workio_cmd *) calloc(1, sizeof(*wc));
1805
if (!wc)
1806
return false;
1807
1808
wc->u.work = (struct work*) malloc(sizeof(*work_in));
1809
if (!wc->u.work)
1810
goto err_out;
1811
1812
wc->cmd = WC_SUBMIT_WORK;
1813
wc->thr = thr;
1814
work_copy(wc->u.work, work_in);
1815
1816
/* send solution to workio thread */
1817
if (!tq_push(thr_info[work_thr_id].q, wc))
1818
goto err_out;
1819
1820
return true;
1821
1822
err_out:
1823
workio_cmd_free(wc);
1824
return false;
1825
}
1826
1827
static void stratum_gen_work(struct stratum_ctx *sctx, struct work *work)
1828
{
1829
uint32_t extraheader[32] = { 0 };
1830
uchar merkle_root[64] = { 0 };
1831
int i, headersize = 0;
1832
1833
pthread_mutex_lock(&sctx->work_lock);
1834
1835
if (jsonrpc_2) {
1836
work_free(work);
1837
work_copy(work, &sctx->work);
1838
pthread_mutex_unlock(&sctx->work_lock);
1839
} else {
1840
free(work->job_id);
1841
work->job_id = strdup(sctx->job.job_id);
1842
work->xnonce2_len = sctx->xnonce2_size;
1843
work->xnonce2 = (uchar*) realloc(work->xnonce2, sctx->xnonce2_size);
1844
memcpy(work->xnonce2, sctx->job.xnonce2, sctx->xnonce2_size);
1845
1846
/* Generate merkle root */
1847
switch (opt_algo) {
1848
case ALGO_DECRED:
1849
// getwork over stratum, getwork merkle + header passed in coinb1
1850
memcpy(merkle_root, sctx->job.coinbase, 32);
1851
headersize = min((int)sctx->job.coinbase_size - 32, sizeof(extraheader));
1852
memcpy(extraheader, &sctx->job.coinbase[32], headersize);
1853
break;
1854
case ALGO_HEAVY:
1855
heavyhash(merkle_root, sctx->job.coinbase, (int)sctx->job.coinbase_size);
1856
break;
1857
case ALGO_GROESTL:
1858
case ALGO_KECCAK:
1859
case ALGO_BLAKECOIN:
1860
SHA256(sctx->job.coinbase, (int) sctx->job.coinbase_size, merkle_root);
1861
break;
1862
case ALGO_SIA:
1863
// getwork over stratum, getwork merkle + header passed in coinb1
1864
memcpy(merkle_root, sctx->job.coinbase, 32);
1865
headersize = min((int)sctx->job.coinbase_size - 32, sizeof(extraheader));
1866
memcpy(extraheader, &sctx->job.coinbase[32], headersize);
1867
break;
1868
default:
1869
sha256d(merkle_root, sctx->job.coinbase, (int) sctx->job.coinbase_size);
1870
}
1871
1872
if (!headersize)
1873
for (i = 0; i < sctx->job.merkle_count; i++) {
1874
memcpy(merkle_root + 32, sctx->job.merkle[i], 32);
1875
if (opt_algo == ALGO_HEAVY)
1876
heavyhash(merkle_root, merkle_root, 64);
1877
else
1878
sha256d(merkle_root, merkle_root, 64);
1879
}
1880
1881
/* Increment extranonce2 */
1882
for (size_t t = 0; t < sctx->xnonce2_size && !(++sctx->job.xnonce2[t]); t++)
1883
;
1884
1885
/* Assemble block header */
1886
memset(work->data, 0, 128);
1887
work->data[0] = le32dec(sctx->job.version);
1888
for (i = 0; i < 8; i++)
1889
work->data[1 + i] = le32dec((uint32_t *) sctx->job.prevhash + i);
1890
for (i = 0; i < 8; i++)
1891
work->data[9 + i] = be32dec((uint32_t *) merkle_root + i);
1892
1893
if (opt_algo == ALGO_DECRED) {
1894
uint32_t* extradata = (uint32_t*) sctx->xnonce1;
1895
for (i = 0; i < 8; i++) // prevhash
1896
work->data[1 + i] = swab32(work->data[1 + i]);
1897
for (i = 0; i < 8; i++) // merkle
1898
work->data[9 + i] = swab32(work->data[9 + i]);
1899
for (i = 0; i < headersize/4; i++) // header
1900
work->data[17 + i] = extraheader[i];
1901
// extradata
1902
for (i = 0; i < sctx->xnonce1_size/4; i++)
1903
work->data[36 + i] = extradata[i];
1904
for (i = 36 + (int) sctx->xnonce1_size/4; i < 45; i++)
1905
work->data[i] = 0;
1906
work->data[37] = (rand()*4) << 8;
1907
sctx->bloc_height = work->data[32];
1908
//applog_hex(work->data, 180);
1909
//applog_hex(&work->data[36], 36);
1910
} else if (opt_algo == ALGO_LBRY) {
1911
for (i = 0; i < 8; i++)
1912
work->data[17 + i] = ((uint32_t*)sctx->job.extra)[i];
1913
work->data[25] = le32dec(sctx->job.ntime);
1914
work->data[26] = le32dec(sctx->job.nbits);
1915
work->data[28] = 0x80000000;
1916
} else if (opt_algo == ALGO_PHI2) {
1917
work->data[17] = le32dec(sctx->job.ntime);
1918
work->data[18] = le32dec(sctx->job.nbits);
1919
for (i = 0; i < 16; i++)
1920
work->data[20 + i] = ((uint32_t*)sctx->job.extra)[i];
1921
//applog_hex(&work->data[0], 144);
1922
} else if (opt_algo == ALGO_SIA) {
1923
for (i = 0; i < 8; i++) // prevhash
1924
work->data[i] = ((uint32_t*)sctx->job.prevhash)[7-i];
1925
work->data[8] = 0; // nonce
1926
work->data[9] = swab32(extraheader[0]);
1927
work->data[9] |= rand() & 0xF0;
1928
work->data[10] = be32dec(sctx->job.ntime);
1929
work->data[11] = be32dec(sctx->job.nbits);
1930
for (i = 0; i < 8; i++) // prevhash
1931
work->data[12+i] = ((uint32_t*)merkle_root)[i];
1932
//applog_hex(&work->data[0], 80);
1933
} else {
1934
work->data[17] = le32dec(sctx->job.ntime);
1935
work->data[18] = le32dec(sctx->job.nbits);
1936
// required ?
1937
work->data[20] = 0x80000000;
1938
work->data[31] = 0x00000280;
1939
}
1940
1941
if (opt_showdiff || opt_max_diff > 0.)
1942
calc_network_diff(work);
1943
1944
if (opt_algo == ALGO_DROP || opt_algo == ALGO_NEOSCRYPT || opt_algo == ALGO_ZR5) {
1945
/* reversed endian */
1946
for (i = 0; i <= 18; i++)
1947
work->data[i] = swab32(work->data[i]);
1948
}
1949
1950
pthread_mutex_unlock(&sctx->work_lock);
1951
1952
if (opt_debug && opt_algo != ALGO_DECRED && opt_algo != ALGO_SIA) {
1953
char *xnonce2str = abin2hex(work->xnonce2, work->xnonce2_len);
1954
applog(LOG_DEBUG, "DEBUG: job_id='%s' extranonce2=%s ntime=%08x",
1955
work->job_id, xnonce2str, swab32(work->data[17]));
1956
free(xnonce2str);
1957
}
1958
1959
switch (opt_algo) {
1960
case ALGO_DROP:
1961
case ALGO_JHA:
1962
case ALGO_SCRYPT:
1963
case ALGO_SCRYPTJANE:
1964
case ALGO_NEOSCRYPT:
1965
case ALGO_PLUCK:
1966
work_set_target(work, sctx->job.diff / (65536.0 * opt_diff_factor));
1967
break;
1968
case ALGO_ALLIUM:
1969
case ALGO_FRESH:
1970
case ALGO_DMD_GR:
1971
case ALGO_GROESTL:
1972
case ALGO_KECCAKC:
1973
case ALGO_LBRY:
1974
case ALGO_LYRA2REV2:
1975
case ALGO_LYRA2V3:
1976
case ALGO_PHI2:
1977
case ALGO_TIMETRAVEL:
1978
case ALGO_BITCORE:
1979
case ALGO_XEVAN:
1980
case ALGO_X16R:
1981
case ALGO_X16S:
1982
case ALGO_X20R:
1983
work_set_target(work, sctx->job.diff / (256.0 * opt_diff_factor));
1984
break;
1985
case ALGO_KECCAK:
1986
case ALGO_LYRA2:
1987
work_set_target(work, sctx->job.diff / (128.0 * opt_diff_factor));
1988
break;
1989
default:
1990
work_set_target(work, sctx->job.diff / opt_diff_factor);
1991
}
1992
1993
if (stratum_diff != sctx->job.diff) {
1994
char sdiff[32] = { 0 };
1995
// store for api stats
1996
stratum_diff = sctx->job.diff;
1997
if (opt_showdiff && work->targetdiff != stratum_diff)
1998
snprintf(sdiff, 32, " (%.5f)", work->targetdiff);
1999
applog(LOG_WARNING, "Stratum difficulty set to %g%s", stratum_diff, sdiff);
2000
}
2001
}
2002
}
2003
2004
bool rpc2_stratum_job(struct stratum_ctx *sctx, json_t *params)
2005
{
2006
bool ret = false;
2007
pthread_mutex_lock(&sctx->work_lock);
2008
ret = rpc2_job_decode(params, &sctx->work);
2009
2010
if (ret) {
2011
work_free(&g_work);
2012
work_copy(&g_work, &sctx->work);
2013
g_work_time = 0;
2014
}
2015
2016
pthread_mutex_unlock(&sctx->work_lock);
2017
2018
return ret;
2019
}
2020
2021
static bool wanna_mine(int thr_id)
2022
{
2023
bool state = true;
2024
2025
if (opt_max_temp > 0.0) {
2026
float temp = cpu_temp(0);
2027
if (temp > opt_max_temp) {
2028
if (!thr_id && !conditional_state[thr_id] && !opt_quiet)
2029
applog(LOG_INFO, "temperature too high (%.0fC), waiting...", temp);
2030
state = false;
2031
}
2032
}
2033
if (opt_max_diff > 0.0 && net_diff > opt_max_diff) {
2034
if (!thr_id && !conditional_state[thr_id] && !opt_quiet)
2035
applog(LOG_INFO, "network diff too high, waiting...");
2036
state = false;
2037
}
2038
if (opt_max_rate > 0.0 && net_hashrate > opt_max_rate) {
2039
if (!thr_id && !conditional_state[thr_id] && !opt_quiet) {
2040
char rate[32];
2041
format_hashrate(opt_max_rate, rate);
2042
applog(LOG_INFO, "network hashrate too high, waiting %s...", rate);
2043
}
2044
state = false;
2045
}
2046
if (thr_id < MAX_CPUS)
2047
conditional_state[thr_id] = (uint8_t) !state;
2048
return state;
2049
}
2050
2051
static void *miner_thread(void *userdata)
2052
{
2053
struct thr_info *mythr = (struct thr_info *) userdata;
2054
int thr_id = mythr->id;
2055
struct work work;
2056
uint32_t max_nonce;
2057
uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20;
2058
time_t tm_rate_log = 0;
2059
time_t firstwork_time = 0;
2060
unsigned char *scratchbuf = NULL;
2061
char s[16];
2062
int i;
2063
2064
memset(&work, 0, sizeof(work));
2065
2066
/* Set worker threads to nice 19 and then preferentially to SCHED_IDLE
2067
* and if that fails, then SCHED_BATCH. No need for this to be an
2068
* error if it fails */
2069
if (!opt_benchmark && opt_priority == 0) {
2070
setpriority(PRIO_PROCESS, 0, 19);
2071
drop_policy();
2072
} else {
2073
int prio = 0;
2074
#ifndef WIN32
2075
prio = 18;
2076
// note: different behavior on linux (-19 to 19)
2077
switch (opt_priority) {
2078
case 1:
2079
prio = 5;
2080
break;
2081
case 2:
2082
prio = 0;
2083
break;
2084
case 3:
2085
prio = -5;
2086
break;
2087
case 4:
2088
prio = -10;
2089
break;
2090
case 5:
2091
prio = -15;
2092
}
2093
if (opt_debug)
2094
applog(LOG_DEBUG, "Thread %d priority %d (nice %d)",
2095
thr_id, opt_priority, prio);
2096
#endif
2097
setpriority(PRIO_PROCESS, 0, prio);
2098
if (opt_priority == 0) {
2099
drop_policy();
2100
}
2101
}
2102
2103
/* Cpu thread affinity */
2104
if (num_cpus > 1) {
2105
if (opt_affinity == -1 && opt_n_threads > 1) {
2106
if (opt_debug)
2107
applog(LOG_DEBUG, "Binding thread %d to cpu %d (mask %x)", thr_id,
2108
thr_id % num_cpus, (1 << (thr_id % num_cpus)));
2109
affine_to_cpu_mask(thr_id, 1UL << (thr_id % num_cpus));
2110
} else if (opt_affinity != -1L) {
2111
if (opt_debug)
2112
applog(LOG_DEBUG, "Binding thread %d to cpu mask %x", thr_id,
2113
opt_affinity);
2114
affine_to_cpu_mask(thr_id, (unsigned long)opt_affinity);
2115
}
2116
}
2117
2118
if (opt_algo == ALGO_SCRYPT) {
2119
scratchbuf = scrypt_buffer_alloc(opt_scrypt_n);
2120
if (!scratchbuf) {
2121
applog(LOG_ERR, "scrypt buffer allocation failed");
2122
pthread_mutex_lock(&applog_lock);
2123
exit(1);
2124
}
2125
}
2126
2127
else if (opt_algo == ALGO_PLUCK) {
2128
scratchbuf = malloc(opt_pluck_n * 1024);
2129
if (!scratchbuf) {
2130
applog(LOG_ERR, "pluck buffer allocation failed");
2131
pthread_mutex_lock(&applog_lock);
2132
exit(1);
2133
}
2134
}
2135
2136
while (1) {
2137
uint64_t hashes_done;
2138
struct timeval tv_start, tv_end, diff;
2139
int64_t max64;
2140
bool regen_work = false;
2141
int wkcmp_offset = 0;
2142
int nonce_oft = 19*sizeof(uint32_t); // 76
2143
int wkcmp_sz = nonce_oft;
2144
int rc = 0;
2145
2146
if (opt_algo == ALGO_DROP || opt_algo == ALGO_ZR5) {
2147
// Duplicates: ignore pok in data[0]
2148
wkcmp_sz -= sizeof(uint32_t);
2149
wkcmp_offset = 1;
2150
} else if (opt_algo == ALGO_DECRED) {
2151
wkcmp_sz = nonce_oft = 140; // 35 * 4
2152
regen_work = true; // ntime not changed ?
2153
} else if (opt_algo == ALGO_LBRY) {
2154
wkcmp_sz = nonce_oft = 108; // 27
2155
//regen_work = true;
2156
} else if (opt_algo == ALGO_SIA) {
2157
nonce_oft = 32;
2158
wkcmp_offset = 32 + 16;
2159
wkcmp_sz = 32; // 35 * 4
2160
}
2161
2162
if (jsonrpc_2) {
2163
wkcmp_sz = nonce_oft = 39;
2164
}
2165
2166
uint32_t *nonceptr = (uint32_t*) (((char*)work.data) + nonce_oft);
2167
2168
if (have_stratum) {
2169
while (!jsonrpc_2 && time(NULL) >= g_work_time + 120)
2170
sleep(1);
2171
2172
while (!stratum.job.diff && opt_algo == ALGO_NEOSCRYPT) {
2173
applog(LOG_DEBUG, "Waiting for Stratum to set the job difficulty");
2174
sleep(1);
2175
}
2176
2177
pthread_mutex_lock(&g_work_lock);
2178
2179
// to clean: is g_work loaded before the memcmp ?
2180
regen_work = regen_work || ( (*nonceptr) >= end_nonce
2181
&& !( memcmp(&work.data[wkcmp_offset], &g_work.data[wkcmp_offset], wkcmp_sz) ||
2182
jsonrpc_2 ? memcmp(((uint8_t*) work.data) + 43, ((uint8_t*) g_work.data) + 43, 33) : 0));
2183
if (regen_work) {
2184
stratum_gen_work(&stratum, &g_work);
2185
}
2186
2187
} else {
2188
2189
int min_scantime = have_longpoll ? LP_SCANTIME : opt_scantime;
2190
/* obtain new work from internal workio thread */
2191
pthread_mutex_lock(&g_work_lock);
2192
if (!have_stratum &&
2193
(time(NULL) - g_work_time >= min_scantime ||
2194
work.data[19] >= end_nonce)) {
2195
if (unlikely(!get_work(mythr, &g_work))) {
2196
applog(LOG_ERR, "work retrieval failed, exiting "
2197
"mining thread %d", mythr->id);
2198
pthread_mutex_unlock(&g_work_lock);
2199
goto out;
2200
}
2201
g_work_time = have_stratum ? 0 : time(NULL);
2202
}
2203
if (have_stratum) {
2204
pthread_mutex_unlock(&g_work_lock);
2205
continue;
2206
}
2207
}
2208
if (memcmp(&work.data[wkcmp_offset], &g_work.data[wkcmp_offset], wkcmp_sz) ||
2209
jsonrpc_2 ? memcmp(((uint8_t*) work.data) + 43, ((uint8_t*) g_work.data) + 43, 33) : 0)
2210
{
2211
work_free(&work);
2212
work_copy(&work, &g_work);
2213
nonceptr = (uint32_t*) (((char*)work.data) + nonce_oft);
2214
*nonceptr = 0xffffffffU / opt_n_threads * thr_id;
2215
if (opt_randomize)
2216
nonceptr[0] += ((rand()*4) & UINT32_MAX) / opt_n_threads;
2217
} else
2218
++(*nonceptr);
2219
pthread_mutex_unlock(&g_work_lock);
2220
work_restart[thr_id].restart = 0;
2221
2222
if (opt_algo == ALGO_DECRED) {
2223
if (have_stratum && strcmp(stratum.job.job_id, work.job_id))
2224
continue; // need to regen g_work..
2225
// extradata: prevent duplicates
2226
nonceptr[1] += 1;
2227
nonceptr[2] |= thr_id;
2228
} else if (opt_algo == ALGO_SIA) {
2229
if (have_stratum && strcmp(stratum.job.job_id, work.job_id))
2230
continue; // need to regen g_work..
2231
// extradata: prevent duplicates
2232
nonceptr[1] += 0x10;
2233
nonceptr[1] |= thr_id;
2234
//applog_hex(nonceptr, 8);
2235
}
2236
2237
// prevent scans before a job is received
2238
// beware, some testnet (decred) are using version 0
2239
// no version in sia draft protocol
2240
if (opt_algo != ALGO_SIA && have_stratum && !work.data[0] && !opt_benchmark) {
2241
sleep(1);
2242
continue;
2243
}
2244
2245
/* conditional mining */
2246
if (!wanna_mine(thr_id)) {
2247
sleep(5);
2248
continue;
2249
}
2250
2251
/* adjust max_nonce to meet target scan time */
2252
if (have_stratum)
2253
max64 = LP_SCANTIME;
2254
else
2255
max64 = g_work_time + (have_longpoll ? LP_SCANTIME : opt_scantime)
2256
- time(NULL);
2257
2258
/* time limit */
2259
if (opt_time_limit && firstwork_time) {
2260
int passed = (int)(time(NULL) - firstwork_time);
2261
int remain = (int)(opt_time_limit - passed);
2262
if (remain < 0) {
2263
if (thr_id != 0) {
2264
sleep(1);
2265
continue;
2266
}
2267
if (opt_benchmark) {
2268
char rate[32];
2269
format_hashrate((double)global_hashrate, rate);
2270
applog(LOG_NOTICE, "Benchmark: %s", rate);
2271
fprintf(stderr, "%llu\n", (long long unsigned int) global_hashrate);
2272
} else {
2273
applog(LOG_NOTICE,
2274
"Mining timeout of %ds reached, exiting...", opt_time_limit);
2275
}
2276
proper_exit(0);
2277
}
2278
if (remain < max64) max64 = remain;
2279
}
2280
2281
max64 *= (int64_t) thr_hashrates[thr_id];
2282
2283
if (max64 <= 0) {
2284
switch (opt_algo) {
2285
case ALGO_SCRYPT:
2286
case ALGO_NEOSCRYPT:
2287
max64 = opt_scrypt_n < 16 ? 0x3ffff : 0x3fffff / opt_scrypt_n;
2288
if (opt_nfactor > 3)
2289
max64 >>= (opt_nfactor - 3);
2290
else if (opt_nfactor > 16)
2291
max64 = 0xF;
2292
break;
2293
case ALGO_AXIOM:
2294
case ALGO_CRYPTOLIGHT:
2295
case ALGO_CRYPTONIGHT:
2296
case ALGO_SCRYPTJANE:
2297
max64 = 0x40LL;
2298
break;
2299
case ALGO_DROP:
2300
case ALGO_PLUCK:
2301
case ALGO_MINOTAUR:
2302
case ALGO_MINOTAURX:
2303
max64 = 0x1ff;
2304
break;
2305
case ALGO_ALLIUM:
2306
case ALGO_LYRA2:
2307
case ALGO_LYRA2REV2:
2308
case ALGO_LYRA2V3:
2309
case ALGO_PHI1612:
2310
case ALGO_PHI2:
2311
case ALGO_TIMETRAVEL:
2312
case ALGO_BITCORE:
2313
case ALGO_XEVAN:
2314
max64 = 0xffff;
2315
break;
2316
case ALGO_C11:
2317
case ALGO_DMD_GR:
2318
case ALGO_FRESH:
2319
case ALGO_GEEK:
2320
case ALGO_GROESTL:
2321
case ALGO_MYR_GR:
2322
case ALGO_SIB:
2323
case ALGO_VELTOR:
2324
case ALGO_X11EVO:
2325
case ALGO_X11:
2326
case ALGO_X12:
2327
case ALGO_X13:
2328
case ALGO_X14:
2329
max64 = 0x3ffff;
2330
break;
2331
case ALGO_LBRY:
2332
case ALGO_SONOA:
2333
case ALGO_TRIBUS:
2334
case ALGO_X15:
2335
case ALGO_X16R:
2336
case ALGO_X16S:
2337
case ALGO_X17:
2338
case ALGO_X20R:
2339
case ALGO_ZR5:
2340
max64 = 0x1ffff;
2341
break;
2342
case ALGO_BMW:
2343
case ALGO_PENTABLAKE:
2344
max64 = 0x3ffff;
2345
break;
2346
case ALGO_SKEIN:
2347
case ALGO_SKEIN2:
2348
max64 = 0x7ffffLL;
2349
break;
2350
case ALGO_BLAKE:
2351
case ALGO_BLAKECOIN:
2352
case ALGO_DECRED:
2353
case ALGO_VANILLA:
2354
max64 = 0x3fffffLL;
2355
break;
2356
case ALGO_SIA:
2357
default:
2358
max64 = 0x1fffffLL;
2359
break;
2360
}
2361
}
2362
if ((*nonceptr) + max64 > end_nonce)
2363
max_nonce = end_nonce;
2364
else
2365
max_nonce = (*nonceptr) + (uint32_t) max64;
2366
2367
hashes_done = 0;
2368
gettimeofday((struct timeval *) &tv_start, NULL);
2369
2370
if (firstwork_time == 0)
2371
firstwork_time = time(NULL);
2372
2373
/* scan nonces for a proof-of-work hash */
2374
switch (opt_algo) {
2375
2376
case ALGO_ALLIUM:
2377
rc = scanhash_allium(thr_id, &work, max_nonce, &hashes_done);
2378
break;
2379
case ALGO_AXIOM:
2380
rc = scanhash_axiom(thr_id, &work, max_nonce, &hashes_done);
2381
break;
2382
case ALGO_BASTION:
2383
rc = scanhash_bastion(thr_id, &work, max_nonce, &hashes_done);
2384
break;
2385
case ALGO_BLAKE:
2386
rc = scanhash_blake(thr_id, &work, max_nonce, &hashes_done);
2387
break;
2388
case ALGO_BLAKECOIN:
2389
rc = scanhash_blakecoin(thr_id, &work, max_nonce, &hashes_done);
2390
break;
2391
case ALGO_BLAKE2B:
2392
rc = scanhash_blake2b(thr_id, &work, max_nonce, &hashes_done);
2393
break;
2394
case ALGO_BLAKE2S:
2395
rc = scanhash_blake2s(thr_id, &work, max_nonce, &hashes_done);
2396
break;
2397
case ALGO_BMW:
2398
rc = scanhash_bmw(thr_id, &work, max_nonce, &hashes_done);
2399
break;
2400
case ALGO_MINOTAUR:
2401
rc = scanhash_minotaur(thr_id, &work, max_nonce, &hashes_done, false);
2402
break;
2403
case ALGO_MINOTAURX:
2404
rc = scanhash_minotaur(thr_id, &work, max_nonce, &hashes_done, true);
2405
break;
2406
case ALGO_C11:
2407
rc = scanhash_c11(thr_id, &work, max_nonce, &hashes_done);
2408
break;
2409
case ALGO_CRYPTOLIGHT:
2410
rc = scanhash_cryptolight(thr_id, &work, max_nonce, &hashes_done);
2411
break;
2412
case ALGO_CRYPTONIGHT:
2413
rc = scanhash_cryptonight(thr_id, &work, max_nonce, &hashes_done);
2414
break;
2415
case ALGO_DECRED:
2416
rc = scanhash_decred(thr_id, &work, max_nonce, &hashes_done);
2417
break;
2418
case ALGO_DROP:
2419
rc = scanhash_drop(thr_id, &work, max_nonce, &hashes_done);
2420
break;
2421
case ALGO_FRESH:
2422
rc = scanhash_fresh(thr_id, &work, max_nonce, &hashes_done);
2423
break;
2424
case ALGO_GEEK:
2425
rc = scanhash_geek(thr_id, &work, max_nonce, &hashes_done);
2426
break;
2427
case ALGO_DMD_GR:
2428
case ALGO_GROESTL:
2429
rc = scanhash_groestl(thr_id, &work, max_nonce, &hashes_done);
2430
break;
2431
case ALGO_KECCAK:
2432
case ALGO_KECCAKC:
2433
rc = scanhash_keccak(thr_id, &work, max_nonce, &hashes_done);
2434
break;
2435
case ALGO_HEAVY:
2436
rc = scanhash_heavy(thr_id, &work, max_nonce, &hashes_done);
2437
break;
2438
case ALGO_JHA:
2439
rc = scanhash_jha(thr_id, &work, max_nonce, &hashes_done);
2440
break;
2441
case ALGO_LBRY:
2442
rc = scanhash_lbry(thr_id, &work, max_nonce, &hashes_done);
2443
break;
2444
case ALGO_LUFFA:
2445
rc = scanhash_luffa(thr_id, &work, max_nonce, &hashes_done);
2446
break;
2447
case ALGO_LYRA2:
2448
rc = scanhash_lyra2(thr_id, &work, max_nonce, &hashes_done);
2449
break;
2450
case ALGO_LYRA2REV2:
2451
rc = scanhash_lyra2rev2(thr_id, &work, max_nonce, &hashes_done);
2452
break;
2453
case ALGO_LYRA2V3:
2454
rc = scanhash_lyra2v3(thr_id, &work, max_nonce, &hashes_done);
2455
break;
2456
case ALGO_MYR_GR:
2457
rc = scanhash_myriad(thr_id, &work, max_nonce, &hashes_done);
2458
break;
2459
case ALGO_NEOSCRYPT:
2460
rc = scanhash_neoscrypt(thr_id, &work, max_nonce, &hashes_done,
2461
0x80000020 | (opt_nfactor << 8));
2462
break;
2463
case ALGO_NIST5:
2464
rc = scanhash_nist5(thr_id, &work, max_nonce, &hashes_done);
2465
break;
2466
case ALGO_PENTABLAKE:
2467
rc = scanhash_pentablake(thr_id, &work, max_nonce, &hashes_done);
2468
break;
2469
case ALGO_PHI1612:
2470
rc = scanhash_phi1612(thr_id, &work, max_nonce, &hashes_done);
2471
break;
2472
case ALGO_PHI2:
2473
rc = scanhash_phi2(thr_id, &work, max_nonce, &hashes_done);
2474
break;
2475
case ALGO_PLUCK:
2476
rc = scanhash_pluck(thr_id, &work, max_nonce, &hashes_done, scratchbuf, opt_pluck_n);
2477
break;
2478
case ALGO_QUARK:
2479
rc = scanhash_quark(thr_id, &work, max_nonce, &hashes_done);
2480
break;
2481
case ALGO_QUBIT:
2482
rc = scanhash_qubit(thr_id, &work, max_nonce, &hashes_done);
2483
break;
2484
case ALGO_RAINFOREST:
2485
rc = scanhash_rf256(thr_id, &work, max_nonce, &hashes_done);
2486
break;
2487
case ALGO_SCRYPT:
2488
rc = scanhash_scrypt(thr_id, &work, max_nonce, &hashes_done, scratchbuf, opt_scrypt_n);
2489
break;
2490
case ALGO_SCRYPTJANE:
2491
rc = scanhash_scryptjane(opt_scrypt_n, thr_id, &work, max_nonce, &hashes_done);
2492
break;
2493
case ALGO_SHAVITE3:
2494
rc = scanhash_ink(thr_id, &work, max_nonce, &hashes_done);
2495
break;
2496
case ALGO_SHA256D:
2497
rc = scanhash_sha256d(thr_id, &work, max_nonce, &hashes_done);
2498
break;
2499
case ALGO_SIA:
2500
rc = scanhash_sia(thr_id, &work, max_nonce, &hashes_done);
2501
break;
2502
case ALGO_SIB:
2503
rc = scanhash_sib(thr_id, &work, max_nonce, &hashes_done);
2504
break;
2505
case ALGO_SKEIN:
2506
rc = scanhash_skein(thr_id, &work, max_nonce, &hashes_done);
2507
break;
2508
case ALGO_SKEIN2:
2509
rc = scanhash_skein2(thr_id, &work, max_nonce, &hashes_done);
2510
break;
2511
case ALGO_SONOA:
2512
rc = scanhash_sonoa(thr_id, &work, max_nonce, &hashes_done);
2513
break;
2514
case ALGO_S3:
2515
rc = scanhash_s3(thr_id, &work, max_nonce, &hashes_done);
2516
break;
2517
case ALGO_TIMETRAVEL:
2518
rc = scanhash_timetravel(thr_id, &work, max_nonce, &hashes_done);
2519
break;
2520
case ALGO_BITCORE:
2521
rc = scanhash_bitcore(thr_id, &work, max_nonce, &hashes_done);
2522
break;
2523
case ALGO_TRIBUS:
2524
rc = scanhash_tribus(thr_id, &work, max_nonce, &hashes_done);
2525
break;
2526
case ALGO_VANILLA:
2527
rc = scanhash_blakecoin(thr_id, &work, max_nonce, &hashes_done);
2528
break;
2529
case ALGO_VELTOR:
2530
rc = scanhash_veltor(thr_id, &work, max_nonce, &hashes_done);
2531
break;
2532
case ALGO_X11EVO:
2533
rc = scanhash_x11evo(thr_id, &work, max_nonce, &hashes_done);
2534
break;
2535
case ALGO_X11:
2536
rc = scanhash_x11(thr_id, &work, max_nonce, &hashes_done);
2537
break;
2538
case ALGO_X12:
2539
rc = scanhash_x12(thr_id, &work, max_nonce, &hashes_done);
2540
break;
2541
case ALGO_X13:
2542
rc = scanhash_x13(thr_id, &work, max_nonce, &hashes_done);
2543
break;
2544
case ALGO_X14:
2545
rc = scanhash_x14(thr_id, &work, max_nonce, &hashes_done);
2546
break;
2547
case ALGO_X15:
2548
rc = scanhash_x15(thr_id, &work, max_nonce, &hashes_done);
2549
break;
2550
case ALGO_X16R:
2551
rc = scanhash_x16r(thr_id, &work, max_nonce, &hashes_done);
2552
break;
2553
case ALGO_X20R:
2554
rc = scanhash_x20r(thr_id, &work, max_nonce, &hashes_done);
2555
break;
2556
case ALGO_X16S:
2557
rc = scanhash_x16s(thr_id, &work, max_nonce, &hashes_done);
2558
break;
2559
case ALGO_X17:
2560
rc = scanhash_x17(thr_id, &work, max_nonce, &hashes_done);
2561
break;
2562
case ALGO_XEVAN:
2563
rc = scanhash_xevan(thr_id, &work, max_nonce, &hashes_done);
2564
break;
2565
case ALGO_ZR5:
2566
rc = scanhash_zr5(thr_id, &work, max_nonce, &hashes_done);
2567
break;
2568
default:
2569
/* should never happen */
2570
goto out;
2571
}
2572
2573
/* record scanhash elapsed time */
2574
gettimeofday(&tv_end, NULL);
2575
timeval_subtract(&diff, &tv_end, &tv_start);
2576
if (diff.tv_usec || diff.tv_sec) {
2577
pthread_mutex_lock(&stats_lock);
2578
thr_hashrates[thr_id] =
2579
hashes_done / (diff.tv_sec + diff.tv_usec * 1e-6);
2580
pthread_mutex_unlock(&stats_lock);
2581
}
2582
if (!opt_quiet && (time(NULL) - tm_rate_log) > opt_maxlograte) {
2583
switch(opt_algo) {
2584
case ALGO_AXIOM:
2585
case ALGO_CRYPTOLIGHT:
2586
case ALGO_CRYPTONIGHT:
2587
case ALGO_PLUCK:
2588
case ALGO_SCRYPTJANE:
2589
case ALGO_MINOTAUR:
2590
case ALGO_MINOTAURX:
2591
applog(LOG_INFO, "CPU #%d: %.2f H/s", thr_id, thr_hashrates[thr_id]);
2592
break;
2593
default:
2594
sprintf(s, thr_hashrates[thr_id] >= 1e6 ? "%.0f" : "%.2f",
2595
thr_hashrates[thr_id] / 1e3);
2596
applog(LOG_INFO, "CPU #%d: %s kH/s", thr_id, s);
2597
break;
2598
}
2599
tm_rate_log = time(NULL);
2600
}
2601
if (opt_benchmark && thr_id == opt_n_threads - 1) {
2602
double hashrate = 0.;
2603
for (i = 0; i < opt_n_threads && thr_hashrates[i]; i++)
2604
hashrate += thr_hashrates[i];
2605
if (i == opt_n_threads) {
2606
switch(opt_algo) {
2607
case ALGO_CRYPTOLIGHT:
2608
case ALGO_CRYPTONIGHT:
2609
case ALGO_AXIOM:
2610
case ALGO_SCRYPTJANE:
2611
sprintf(s, "%.3f", hashrate);
2612
applog(LOG_NOTICE, "Total: %s H/s", s);
2613
break;
2614
default:
2615
sprintf(s, hashrate >= 1e6 ? "%.0f" : "%.2f", hashrate / 1000);
2616
applog(LOG_NOTICE, "Total: %s kH/s", s);
2617
break;
2618
}
2619
global_hashrate = (uint64_t) hashrate;
2620
}
2621
}
2622
2623
/* if nonce found, submit work */
2624
if (rc && !opt_benchmark) {
2625
if (!submit_work(mythr, &work))
2626
break;
2627
// prevent stale work in solo
2628
// we can't submit twice a block!
2629
if (!have_stratum && !have_longpoll) {
2630
pthread_mutex_lock(&g_work_lock);
2631
// will force getwork
2632
g_work_time = 0;
2633
pthread_mutex_unlock(&g_work_lock);
2634
continue;
2635
}
2636
}
2637
2638
}
2639
2640
out:
2641
tq_freeze(mythr->q);
2642
2643
return NULL;
2644
}
2645
2646
void restart_threads(void)
2647
{
2648
int i;
2649
2650
for (i = 0; i < opt_n_threads; i++)
2651
work_restart[i].restart = 1;
2652
}
2653
2654
static void *longpoll_thread(void *userdata)
2655
{
2656
struct thr_info *mythr = (struct thr_info*) userdata;
2657
CURL *curl = NULL;
2658
char *copy_start, *hdr_path = NULL, *lp_url = NULL;
2659
bool need_slash = false;
2660
2661
curl = curl_easy_init();
2662
if (unlikely(!curl)) {
2663
applog(LOG_ERR, "CURL init failed");
2664
goto out;
2665
}
2666
2667
start:
2668
hdr_path = (char*) tq_pop(mythr->q, NULL);
2669
if (!hdr_path)
2670
goto out;
2671
2672
/* full URL */
2673
if (strstr(hdr_path, "://")) {
2674
lp_url = hdr_path;
2675
hdr_path = NULL;
2676
}
2677
2678
/* absolute path, on current server */
2679
else {
2680
copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path;
2681
if (rpc_url[strlen(rpc_url) - 1] != '/')
2682
need_slash = true;
2683
2684
lp_url = (char*) malloc(strlen(rpc_url) + strlen(copy_start) + 2);
2685
if (!lp_url)
2686
goto out;
2687
2688
sprintf(lp_url, "%s%s%s", rpc_url, need_slash ? "/" : "", copy_start);
2689
}
2690
2691
if (!opt_quiet)
2692
applog(LOG_BLUE, "Long-polling on %s", lp_url);
2693
2694
while (1) {
2695
json_t *val;
2696
char *req = NULL;
2697
int err;
2698
2699
if (jsonrpc_2) {
2700
char s[128];
2701
pthread_mutex_lock(&rpc2_login_lock);
2702
if (!strlen(rpc2_id)) {
2703
sleep(1);
2704
continue;
2705
}
2706
snprintf(s, 128, "{\"method\": \"getjob\", \"params\": {\"id\": \"%s\"}, \"id\":1}\r\n", rpc2_id);
2707
pthread_mutex_unlock(&rpc2_login_lock);
2708
val = json_rpc2_call(curl, rpc_url, rpc_userpass, s, &err, JSON_RPC_LONGPOLL);
2709
} else {
2710
if (have_gbt) {
2711
// Parameters for MinX BlockTemplate BEGIN
2712
/*
2713
req = (char*) malloc(strlen(gbt_lp_req) + strlen(lp_id) + 1);
2714
sprintf(req, gbt_lp_req, lp_id);
2715
*/
2716
if(!opt_minotaurx) {
2717
req = (char*) malloc(strlen(gbt_lp_req) + strlen(lp_id) + 1);
2718
sprintf(req, gbt_lp_req, lp_id);
2719
} else {
2720
req = (char*) malloc(strlen(gbt_lp_req_minx) + strlen(lp_id) + 1);
2721
sprintf(req, gbt_lp_req_minx, lp_id);
2722
}
2723
// Parameters for MinX BlockTemplate END
2724
}
2725
val = json_rpc_call(curl, rpc_url, rpc_userpass, getwork_req, &err, JSON_RPC_LONGPOLL);
2726
val = json_rpc_call(curl, lp_url, rpc_userpass,
2727
req ? req : getwork_req, &err,
2728
JSON_RPC_LONGPOLL);
2729
free(req);
2730
}
2731
2732
if (have_stratum) {
2733
if (val)
2734
json_decref(val);
2735
goto out;
2736
}
2737
if (likely(val)) {
2738
bool rc;
2739
char *start_job_id;
2740
double start_diff = 0.0;
2741
json_t *res, *soval;
2742
res = json_object_get(val, "result");
2743
if (!jsonrpc_2) {
2744
soval = json_object_get(res, "submitold");
2745
submit_old = soval ? json_is_true(soval) : false;
2746
}
2747
pthread_mutex_lock(&g_work_lock);
2748
start_job_id = g_work.job_id ? strdup(g_work.job_id) : NULL;
2749
if (have_gbt)
2750
rc = gbt_work_decode(res, &g_work);
2751
else
2752
rc = work_decode(res, &g_work);
2753
if (rc) {
2754
bool newblock = g_work.job_id && strcmp(start_job_id, g_work.job_id);
2755
newblock |= (start_diff != net_diff); // the best is the height but... longpoll...
2756
if (newblock) {
2757
start_diff = net_diff;
2758
if (!opt_quiet) {
2759
char netinfo[64] = { 0 };
2760
if (net_diff > 0.) {
2761
sprintf(netinfo, ", diff %.3f", net_diff);
2762
}
2763
if (opt_showdiff)
2764
sprintf(&netinfo[strlen(netinfo)], ", target %.3f", g_work.targetdiff);
2765
applog(LOG_BLUE, "%s detected new block%s", short_url, netinfo);
2766
}
2767
time(&g_work_time);
2768
restart_threads();
2769
}
2770
}
2771
free(start_job_id);
2772
pthread_mutex_unlock(&g_work_lock);
2773
json_decref(val);
2774
} else {
2775
pthread_mutex_lock(&g_work_lock);
2776
g_work_time -= LP_SCANTIME;
2777
pthread_mutex_unlock(&g_work_lock);
2778
if (err == CURLE_OPERATION_TIMEDOUT) {
2779
restart_threads();
2780
} else {
2781
have_longpoll = false;
2782
restart_threads();
2783
free(hdr_path);
2784
free(lp_url);
2785
lp_url = NULL;
2786
sleep(opt_fail_pause);
2787
goto start;
2788
}
2789
}
2790
}
2791
2792
out:
2793
free(hdr_path);
2794
free(lp_url);
2795
tq_freeze(mythr->q);
2796
if (curl)
2797
curl_easy_cleanup(curl);
2798
2799
return NULL;
2800
}
2801
2802
static bool stratum_handle_response(char *buf)
2803
{
2804
json_t *val, *err_val, *res_val, *id_val;
2805
json_error_t err;
2806
bool ret = false;
2807
bool valid = false;
2808
2809
val = JSON_LOADS(buf, &err);
2810
if (!val) {
2811
applog(LOG_INFO, "JSON decode failed(%d): %s", err.line, err.text);
2812
goto out;
2813
}
2814
2815
res_val = json_object_get(val, "result");
2816
err_val = json_object_get(val, "error");
2817
id_val = json_object_get(val, "id");
2818
2819
if (!id_val || json_is_null(id_val))
2820
goto out;
2821
2822
if (jsonrpc_2)
2823
{
2824
if (!res_val && !err_val)
2825
goto out;
2826
2827
json_t *status = json_object_get(res_val, "status");
2828
if(status) {
2829
const char *s = json_string_value(status);
2830
valid = !strcmp(s, "OK") && json_is_null(err_val);
2831
} else {
2832
valid = json_is_null(err_val);
2833
}
2834
share_result(valid, NULL, err_val ? json_string_value(err_val) : NULL);
2835
2836
} else {
2837
2838
if (!res_val || json_integer_value(id_val) < 4)
2839
goto out;
2840
valid = json_is_true(res_val);
2841
share_result(valid, NULL, err_val ? json_string_value(json_array_get(err_val, 1)) : NULL);
2842
}
2843
2844
ret = true;
2845
2846
out:
2847
if (val)
2848
json_decref(val);
2849
2850
return ret;
2851
}
2852
2853
static void *stratum_thread(void *userdata)
2854
{
2855
struct thr_info *mythr = (struct thr_info *) userdata;
2856
char *s;
2857
2858
stratum.url = (char*) tq_pop(mythr->q, NULL);
2859
if (!stratum.url)
2860
goto out;
2861
applog(LOG_INFO, "Starting Stratum on %s", stratum.url);
2862
2863
while (1) {
2864
int failures = 0;
2865
2866
if (stratum_need_reset) {
2867
stratum_need_reset = false;
2868
stratum_disconnect(&stratum);
2869
if (strcmp(stratum.url, rpc_url)) {
2870
free(stratum.url);
2871
stratum.url = strdup(rpc_url);
2872
applog(LOG_BLUE, "Connection changed to %s", short_url);
2873
} else if (!opt_quiet) {
2874
applog(LOG_DEBUG, "Stratum connection reset");
2875
}
2876
}
2877
2878
while (!stratum.curl) {
2879
pthread_mutex_lock(&g_work_lock);
2880
g_work_time = 0;
2881
pthread_mutex_unlock(&g_work_lock);
2882
restart_threads();
2883
2884
if (!stratum_connect(&stratum, stratum.url)
2885
|| !stratum_subscribe(&stratum)
2886
|| !stratum_authorize(&stratum, rpc_user, rpc_pass)) {
2887
stratum_disconnect(&stratum);
2888
if (opt_retries >= 0 && ++failures > opt_retries) {
2889
applog(LOG_ERR, "...terminating workio thread");
2890
tq_push(thr_info[work_thr_id].q, NULL);
2891
goto out;
2892
}
2893
if (!opt_benchmark)
2894
applog(LOG_ERR, "...retry after %d seconds", opt_fail_pause);
2895
sleep(opt_fail_pause);
2896
}
2897
2898
if (jsonrpc_2) {
2899
work_free(&g_work);
2900
work_copy(&g_work, &stratum.work);
2901
}
2902
}
2903
2904
if (stratum.job.job_id &&
2905
(!g_work_time || strcmp(stratum.job.job_id, g_work.job_id)) )
2906
{
2907
pthread_mutex_lock(&g_work_lock);
2908
stratum_gen_work(&stratum, &g_work);
2909
time(&g_work_time);
2910
pthread_mutex_unlock(&g_work_lock);
2911
2912
if (stratum.job.clean || jsonrpc_2) {
2913
static uint32_t last_bloc_height;
2914
if (!opt_quiet && last_bloc_height != stratum.bloc_height) {
2915
last_bloc_height = stratum.bloc_height;
2916
if (net_diff > 0.)
2917
applog(LOG_BLUE, "%s block %d, diff %.3f", algo_names[opt_algo],
2918
stratum.bloc_height, net_diff);
2919
else
2920
applog(LOG_BLUE, "%s %s block %d", short_url, algo_names[opt_algo],
2921
stratum.bloc_height);
2922
}
2923
restart_threads();
2924
} else if (opt_debug && !opt_quiet) {
2925
applog(LOG_BLUE, "%s asks job %lu for block %d", short_url,
2926
strtoul(stratum.job.job_id, NULL, 16), stratum.bloc_height);
2927
}
2928
}
2929
2930
if (!stratum_socket_full(&stratum, opt_timeout)) {
2931
applog(LOG_ERR, "Stratum connection timeout");
2932
s = NULL;
2933
} else
2934
s = stratum_recv_line(&stratum);
2935
if (!s) {
2936
stratum_disconnect(&stratum);
2937
applog(LOG_ERR, "Stratum connection interrupted");
2938
continue;
2939
}
2940
if (!stratum_handle_method(&stratum, s))
2941
stratum_handle_response(s);
2942
free(s);
2943
}
2944
out:
2945
return NULL;
2946
}
2947
2948
static void show_version_and_exit(void)
2949
{
2950
printf(" built "
2951
#ifdef _MSC_VER
2952
"with VC++ %d", msver());
2953
#elif defined(__GNUC__)
2954
"with GCC ");
2955
printf("%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
2956
#endif
2957
printf(" the " __DATE__ "\n");
2958
2959
// Note: if compiled with cpu opts (instruction sets),
2960
// the binary is no more compatible with older ones!
2961
printf(" compiled for"
2962
#if defined(__ARM_NEON__)
2963
" ARM NEON"
2964
#elif defined(__AVX2__)
2965
" AVX2"
2966
#elif defined(__AVX__)
2967
" AVX"
2968
#elif defined(__XOP__)
2969
" XOP"
2970
#elif defined(__SSE4_1__)
2971
" SSE4"
2972
#elif defined(_M_X64) || defined(__x86_64__)
2973
" x64"
2974
#elif defined(_M_IX86) || defined(__x86__)
2975
" x86"
2976
#else
2977
" general use"
2978
#endif
2979
"\n");
2980
2981
printf(" config features:"
2982
#if defined(USE_ASM) && defined(__i386__)
2983
" i386"
2984
#endif
2985
#if defined(USE_ASM) && defined(__x86_64__)
2986
" x86_64"
2987
#endif
2988
#if defined(USE_ASM) && (defined(__i386__) || defined(__x86_64__))
2989
" SSE2"
2990
#endif
2991
#if defined(__x86_64__) && defined(USE_XOP)
2992
" XOP"
2993
#endif
2994
#if defined(__x86_64__) && defined(USE_AVX)
2995
" AVX"
2996
#endif
2997
#if defined(__x86_64__) && defined(USE_AVX2)
2998
" AVX2"
2999
#endif
3000
#if defined(USE_ASM) && defined(__arm__) && defined(__APCS_32__)
3001
" ARM"
3002
#if defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) || \
3003
defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_6__) || \
3004
defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || \
3005
defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_6T2__) || \
3006
defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || \
3007
defined(__ARM_ARCH_7__) || \
3008
defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \
3009
defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
3010
" ARMv5E"
3011
#endif
3012
#if defined(__ARM_NEON__)
3013
" NEON"
3014
#endif
3015
#endif
3016
"\n\n");
3017
/* dependencies versions */
3018
printf("%s\n", curl_version());
3019
#ifdef JANSSON_VERSION
3020
printf("jansson/%s ", JANSSON_VERSION);
3021
#endif
3022
#ifdef PTW32_VERSION
3023
printf("pthreads/%d.%d.%d.%d ", PTW32_VERSION);
3024
#endif
3025
printf("\n");
3026
exit(0);
3027
}
3028
3029
static void show_usage_and_exit(int status)
3030
{
3031
if (status)
3032
fprintf(stderr, "Try `" PACKAGE_NAME " --help' for more information.\n");
3033
else
3034
printf(usage);
3035
exit(status);
3036
}
3037
3038
static void strhide(char *s)
3039
{
3040
if (*s) *s++ = 'x';
3041
while (*s) *s++ = '\0';
3042
}
3043
3044
void parse_arg(int key, char *arg)
3045
{
3046
char *p;
3047
int v, i;
3048
uint64_t ul;
3049
double d;
3050
3051
switch(key) {
3052
case 'a':
3053
for (i = 0; i < ALGO_COUNT; i++) {
3054
v = (int) strlen(algo_names[i]);
3055
if (v && !strncasecmp(arg, algo_names[i], v)) {
3056
if (arg[v] == '\0') {
3057
opt_algo = (enum algos) i;
3058
break;
3059
}
3060
if (arg[v] == ':') {
3061
char *ep;
3062
v = strtol(arg+v+1, &ep, 10);
3063
if (*ep || (i == ALGO_SCRYPT && v & (v-1)) || v < 2)
3064
continue;
3065
opt_algo = (enum algos) i;
3066
opt_scrypt_n = v;
3067
break;
3068
}
3069
}
3070
}
3071
3072
if (i == ALGO_COUNT) {
3073
3074
if (strstr(arg, ":")) {
3075
// pick and strip the optional factor
3076
char *nf = strstr(arg, ":");
3077
opt_scrypt_n = strtol(&nf[1], NULL, 10);
3078
*nf = '\0';
3079
}
3080
3081
// some aliases...
3082
if (!strcasecmp("blake2", arg))
3083
i = opt_algo = ALGO_BLAKE2S;
3084
else if (!strcasecmp("cryptonight-light", arg))
3085
i = opt_algo = ALGO_CRYPTOLIGHT;
3086
else if (!strcasecmp("flax", arg))
3087
i = opt_algo = ALGO_C11;
3088
else if (!strcasecmp("diamond", arg))
3089
i = opt_algo = ALGO_DMD_GR;
3090
else if (!strcasecmp("droplp", arg))
3091
i = opt_algo = ALGO_DROP;
3092
else if (!strcasecmp("jackpot", arg))
3093
i = opt_algo = ALGO_JHA;
3094
else if (!strcasecmp("lyra2", arg))
3095
i = opt_algo = ALGO_LYRA2;
3096
else if (!strcasecmp("lyra2v2", arg))
3097
i = opt_algo = ALGO_LYRA2REV2;
3098
else if (!strcasecmp("lyra2rev3", arg))
3099
i = opt_algo = ALGO_LYRA2V3;
3100
else if (!strcasecmp("monero", arg))
3101
i = opt_algo = ALGO_CRYPTONIGHT;
3102
else if (!strcasecmp("phi", arg))
3103
i = opt_algo = ALGO_PHI1612;
3104
else if (!strcasecmp("scryptjane", arg))
3105
i = opt_algo = ALGO_SCRYPTJANE;
3106
else if (!strcasecmp("sibcoin", arg))
3107
i = opt_algo = ALGO_SIB;
3108
else if (!strcasecmp("timetravel10", arg))
3109
i = opt_algo = ALGO_BITCORE;
3110
else if (!strcasecmp("ziftr", arg))
3111
i = opt_algo = ALGO_ZR5;
3112
else
3113
applog(LOG_ERR, "Unknown algo parameter '%s'", arg);
3114
}
3115
if (i == ALGO_COUNT) {
3116
show_usage_and_exit(1);
3117
}
3118
if (!opt_nfactor && opt_algo == ALGO_SCRYPT)
3119
opt_nfactor = 9;
3120
if (opt_algo == ALGO_SCRYPTJANE && opt_scrypt_n == 0)
3121
opt_scrypt_n = 5;
3122
break;
3123
case 'b':
3124
p = strstr(arg, ":");
3125
if (p) {
3126
/* ip:port */
3127
if (p - arg > 0) {
3128
free(opt_api_allow);
3129
opt_api_allow = strdup(arg);
3130
opt_api_allow[p - arg] = '\0';
3131
}
3132
opt_api_listen = atoi(p + 1);
3133
}
3134
else if (arg && strstr(arg, ".")) {
3135
/* ip only */
3136
free(opt_api_allow);
3137
opt_api_allow = strdup(arg);
3138
}
3139
else if (arg) {
3140
/* port or 0 to disable */
3141
opt_api_listen = atoi(arg);
3142
}
3143
break;
3144
case 1030: /* --api-remote */
3145
opt_api_remote = 1;
3146
break;
3147
case 'n':
3148
if (opt_algo == ALGO_NEOSCRYPT) {
3149
v = atoi(arg);
3150
/* Nfactor = lb(N) - 1; N = (1 << (Nfactor + 1)) */
3151
if ((v < 0) || (v > 30)) {
3152
fprintf(stderr, "incorrect Nfactor %d\n", v);
3153
show_usage_and_exit(1);
3154
}
3155
opt_nfactor = v;
3156
}
3157
break;
3158
case 'B':
3159
opt_background = true;
3160
use_colors = false;
3161
break;
3162
case 'c': {
3163
json_error_t err;
3164
json_t *config;
3165
if (arg && strstr(arg, "://")) {
3166
config = json_load_url(arg, &err);
3167
} else {
3168
config = JSON_LOADF(arg, &err);
3169
}
3170
if (!json_is_object(config)) {
3171
if (err.line < 0)
3172
fprintf(stderr, "%s\n", err.text);
3173
else
3174
fprintf(stderr, "%s:%d: %s\n",
3175
arg, err.line, err.text);
3176
} else {
3177
parse_config(config, arg);
3178
json_decref(config);
3179
}
3180
break;
3181
}
3182
case 'C':
3183
break;
3184
case 'q':
3185
opt_quiet = true;
3186
break;
3187
case 'D':
3188
opt_debug = true;
3189
break;
3190
case 'p':
3191
free(rpc_pass);
3192
rpc_pass = strdup(arg);
3193
strhide(arg);
3194
break;
3195
case 'P':
3196
opt_protocol = true;
3197
break;
3198
case 'r':
3199
v = atoi(arg);
3200
if (v < -1 || v > 9999) /* sanity check */
3201
show_usage_and_exit(1);
3202
opt_retries = v;
3203
break;
3204
case 'R':
3205
v = atoi(arg);
3206
if (v < 1 || v > 9999) /* sanity check */
3207
show_usage_and_exit(1);
3208
opt_fail_pause = v;
3209
break;
3210
case 's':
3211
v = atoi(arg);
3212
if (v < 1 || v > 9999) /* sanity check */
3213
show_usage_and_exit(1);
3214
opt_scantime = v;
3215
break;
3216
case 'T':
3217
v = atoi(arg);
3218
if (v < 1 || v > 99999) /* sanity check */
3219
show_usage_and_exit(1);
3220
opt_timeout = v;
3221
break;
3222
case 't':
3223
v = atoi(arg);
3224
if (v < 0 || v > 9999) /* sanity check */
3225
show_usage_and_exit(1);
3226
opt_n_threads = v;
3227
break;
3228
case 'u':
3229
free(rpc_user);
3230
rpc_user = strdup(arg);
3231
break;
3232
case 'o': { /* --url */
3233
char *ap, *hp;
3234
ap = strstr(arg, "://");
3235
ap = ap ? ap + 3 : arg;
3236
hp = strrchr(arg, '@');
3237
if (hp) {
3238
*hp = '\0';
3239
p = strchr(ap, ':');
3240
if (p) {
3241
free(rpc_userpass);
3242
rpc_userpass = strdup(ap);
3243
free(rpc_user);
3244
rpc_user = (char*) calloc(p - ap + 1, 1);
3245
strncpy(rpc_user, ap, p - ap);
3246
free(rpc_pass);
3247
rpc_pass = strdup(++p);
3248
if (*p) *p++ = 'x';
3249
v = (int) strlen(hp + 1) + 1;
3250
memmove(p + 1, hp + 1, v);
3251
memset(p + v, 0, hp - p);
3252
hp = p;
3253
} else {
3254
free(rpc_user);
3255
rpc_user = strdup(ap);
3256
}
3257
*hp++ = '@';
3258
} else
3259
hp = ap;
3260
if (ap != arg) {
3261
if (strncasecmp(arg, "http://", 7) &&
3262
strncasecmp(arg, "https://", 8) &&
3263
strncasecmp(arg, "stratum+tcp://", 14)) {
3264
fprintf(stderr, "unknown protocol -- '%s'\n", arg);
3265
show_usage_and_exit(1);
3266
}
3267
free(rpc_url);
3268
rpc_url = strdup(arg);
3269
strcpy(rpc_url + (ap - arg), hp);
3270
short_url = &rpc_url[ap - arg];
3271
} else {
3272
if (*hp == '\0' || *hp == '/') {
3273
fprintf(stderr, "invalid URL -- '%s'\n",
3274
arg);
3275
show_usage_and_exit(1);
3276
}
3277
free(rpc_url);
3278
rpc_url = (char*) malloc(strlen(hp) + 8);
3279
sprintf(rpc_url, "http://%s", hp);
3280
short_url = &rpc_url[sizeof("http://")-1];
3281
}
3282
have_stratum = !opt_benchmark && !strncasecmp(rpc_url, "stratum", 7);
3283
break;
3284
}
3285
case 'O': /* --userpass */
3286
p = strchr(arg, ':');
3287
if (!p) {
3288
fprintf(stderr, "invalid username:password pair -- '%s'\n", arg);
3289
show_usage_and_exit(1);
3290
}
3291
free(rpc_userpass);
3292
rpc_userpass = strdup(arg);
3293
free(rpc_user);
3294
rpc_user = (char*) calloc(p - arg + 1, 1);
3295
strncpy(rpc_user, arg, p - arg);
3296
free(rpc_pass);
3297
rpc_pass = strdup(++p);
3298
strhide(p);
3299
break;
3300
case 'x': /* --proxy */
3301
if (!strncasecmp(arg, "socks4://", 9))
3302
opt_proxy_type = CURLPROXY_SOCKS4;
3303
else if (!strncasecmp(arg, "socks5://", 9))
3304
opt_proxy_type = CURLPROXY_SOCKS5;
3305
#if LIBCURL_VERSION_NUM >= 0x071200
3306
else if (!strncasecmp(arg, "socks4a://", 10))
3307
opt_proxy_type = CURLPROXY_SOCKS4A;
3308
else if (!strncasecmp(arg, "socks5h://", 10))
3309
opt_proxy_type = CURLPROXY_SOCKS5_HOSTNAME;
3310
#endif
3311
else
3312
opt_proxy_type = CURLPROXY_HTTP;
3313
free(opt_proxy);
3314
opt_proxy = strdup(arg);
3315
break;
3316
case 1001:
3317
free(opt_cert);
3318
opt_cert = strdup(arg);
3319
break;
3320
case 1002:
3321
use_colors = false;
3322
break;
3323
case 1003:
3324
want_longpoll = false;
3325
break;
3326
case 1005:
3327
opt_benchmark = true;
3328
want_longpoll = false;
3329
want_stratum = false;
3330
have_stratum = false;
3331
break;
3332
case 1006:
3333
print_hash_tests();
3334
exit(0);
3335
case 1007:
3336
want_stratum = false;
3337
opt_extranonce = false;
3338
break;
3339
case 1008:
3340
opt_time_limit = atoi(arg);
3341
break;
3342
case 1009:
3343
opt_redirect = false;
3344
break;
3345
case 1010:
3346
allow_getwork = false;
3347
break;
3348
case 1011:
3349
have_gbt = false;
3350
break;
3351
case 1012:
3352
opt_extranonce = false;
3353
break;
3354
case 1013:
3355
opt_showdiff = true;
3356
break;
3357
case 1014:
3358
opt_showdiff = false;
3359
break;
3360
case 1016: /* --coinbase-addr */
3361
pk_script_size = address_to_script(pk_script, sizeof(pk_script), arg);
3362
if (!pk_script_size) {
3363
fprintf(stderr, "invalid address -- '%s'\n", arg);
3364
show_usage_and_exit(1);
3365
}
3366
break;
3367
case 1015: /* --coinbase-sig */
3368
if (strlen(arg) + 1 > sizeof(coinbase_sig)) {
3369
fprintf(stderr, "coinbase signature too long\n");
3370
show_usage_and_exit(1);
3371
}
3372
strcpy(coinbase_sig, arg);
3373
break;
3374
case 'f':
3375
d = atof(arg);
3376
if (d == 0.) /* --diff-factor */
3377
show_usage_and_exit(1);
3378
opt_diff_factor = d;
3379
break;
3380
case 'm':
3381
d = atof(arg);
3382
if (d == 0.) /* --diff-multiplier */
3383
show_usage_and_exit(1);
3384
opt_diff_factor = 1.0/d;
3385
break;
3386
case 'S':
3387
use_syslog = true;
3388
use_colors = false;
3389
break;
3390
case 1019: // max-log-rate
3391
opt_maxlograte = atoi(arg);
3392
break;
3393
case 1020:
3394
p = strstr(arg, "0x");
3395
if (p)
3396
ul = strtoul(p, NULL, 16);
3397
else
3398
ul = atol(arg);
3399
if (ul > (1UL<<num_cpus)-1)
3400
ul = -1;
3401
opt_affinity = ul;
3402
break;
3403
case 1021:
3404
v = atoi(arg);
3405
if (v < 0 || v > 5) /* sanity check */
3406
show_usage_and_exit(1);
3407
opt_priority = v;
3408
break;
3409
case 1060: // max-temp
3410
d = atof(arg);
3411
opt_max_temp = d;
3412
break;
3413
case 1061: // max-diff
3414
d = atof(arg);
3415
opt_max_diff = d;
3416
break;
3417
case 1062: // max-rate
3418
d = atof(arg);
3419
p = strstr(arg, "K");
3420
if (p) d *= 1e3;
3421
p = strstr(arg, "M");
3422
if (p) d *= 1e6;
3423
p = strstr(arg, "G");
3424
if (p) d *= 1e9;
3425
opt_max_rate = d;
3426
break;
3427
case 1024:
3428
opt_randomize = true;
3429
break;
3430
case 'V':
3431
show_version_and_exit();
3432
case 'h':
3433
show_usage_and_exit(0);
3434
default:
3435
show_usage_and_exit(1);
3436
}
3437
}
3438
3439
void parse_config(json_t *config, char *ref)
3440
{
3441
int i;
3442
json_t *val;
3443
3444
for (i = 0; i < ARRAY_SIZE(options); i++) {
3445
if (!options[i].name)
3446
break;
3447
3448
val = json_object_get(config, options[i].name);
3449
if (!val)
3450
continue;
3451
if (options[i].has_arg && json_is_string(val)) {
3452
char *s = strdup(json_string_value(val));
3453
if (!s)
3454
break;
3455
parse_arg(options[i].val, s);
3456
free(s);
3457
}
3458
else if (options[i].has_arg && json_is_integer(val)) {
3459
char buf[16];
3460
sprintf(buf, "%d", (int)json_integer_value(val));
3461
parse_arg(options[i].val, buf);
3462
}
3463
else if (options[i].has_arg && json_is_real(val)) {
3464
char buf[16];
3465
sprintf(buf, "%f", json_real_value(val));
3466
parse_arg(options[i].val, buf);
3467
}
3468
else if (!options[i].has_arg) {
3469
if (json_is_true(val))
3470
parse_arg(options[i].val, "");
3471
}
3472
else
3473
applog(LOG_ERR, "JSON option %s invalid",
3474
options[i].name);
3475
}
3476
}
3477
3478
static void parse_cmdline(int argc, char *argv[])
3479
{
3480
int key;
3481
3482
while (1) {
3483
#if HAVE_GETOPT_LONG
3484
key = getopt_long(argc, argv, short_options, options, NULL);
3485
#else
3486
key = getopt(argc, argv, short_options);
3487
#endif
3488
if (key < 0)
3489
break;
3490
3491
parse_arg(key, optarg);
3492
}
3493
if (optind < argc) {
3494
fprintf(stderr, "%s: unsupported non-option argument -- '%s'\n",
3495
argv[0], argv[optind]);
3496
show_usage_and_exit(1);
3497
}
3498
}
3499
3500
#ifndef WIN32
3501
static void signal_handler(int sig)
3502
{
3503
switch (sig) {
3504
case SIGHUP:
3505
applog(LOG_INFO, "SIGHUP received");
3506
break;
3507
case SIGINT:
3508
applog(LOG_INFO, "SIGINT received, exiting");
3509
proper_exit(0);
3510
break;
3511
case SIGTERM:
3512
applog(LOG_INFO, "SIGTERM received, exiting");
3513
proper_exit(0);
3514
break;
3515
}
3516
}
3517
#else
3518
BOOL WINAPI ConsoleHandler(DWORD dwType)
3519
{
3520
switch (dwType) {
3521
case CTRL_C_EVENT:
3522
applog(LOG_INFO, "CTRL_C_EVENT received, exiting");
3523
proper_exit(0);
3524
break;
3525
case CTRL_BREAK_EVENT:
3526
applog(LOG_INFO, "CTRL_BREAK_EVENT received, exiting");
3527
proper_exit(0);
3528
break;
3529
default:
3530
return false;
3531
}
3532
return true;
3533
}
3534
#endif
3535
3536
static int thread_create(struct thr_info *thr, void* func)
3537
{
3538
int err = 0;
3539
pthread_attr_init(&thr->attr);
3540
err = pthread_create(&thr->pth, &thr->attr, func, thr);
3541
pthread_attr_destroy(&thr->attr);
3542
return err;
3543
}
3544
3545
static void show_credits()
3546
{
3547
printf("** " PACKAGE_NAME " " PACKAGE_VERSION " by Tanner^LCC **\n");
3548
printf("LCC donation address: CashCFfv8CmdWo6wyMGQWtmQnaToyhgsWr\n\n");
3549
}
3550
3551
void get_defconfig_path(char *out, size_t bufsize, char *argv0);
3552
3553
int main(int argc, char *argv[]) {
3554
struct thr_info *thr;
3555
long flags;
3556
int i, err;
3557
3558
pthread_mutex_init(&applog_lock, NULL);
3559
3560
show_credits();
3561
3562
rpc_user = strdup("");
3563
rpc_pass = strdup("");
3564
opt_api_allow = strdup("127.0.0.1"); /* 0.0.0.0 for all ips */
3565
3566
#if defined(WIN32)
3567
SYSTEM_INFO sysinfo;
3568
GetSystemInfo(&sysinfo);
3569
num_cpus = sysinfo.dwNumberOfProcessors;
3570
#elif defined(_SC_NPROCESSORS_CONF)
3571
num_cpus = sysconf(_SC_NPROCESSORS_CONF);
3572
#elif defined(CTL_HW) && defined(HW_NCPU)
3573
int req[] = { CTL_HW, HW_NCPU };
3574
size_t len = sizeof(num_cpus);
3575
sysctl(req, 2, &num_cpus, &len, NULL, 0);
3576
#else
3577
num_cpus = 1;
3578
#endif
3579
if (num_cpus < 1)
3580
num_cpus = 1;
3581
3582
/* parse command line */
3583
parse_cmdline(argc, argv);
3584
3585
if (!opt_benchmark && !rpc_url) {
3586
// try default config file in binary folder
3587
char defconfig[MAX_PATH] = { 0 };
3588
get_defconfig_path(defconfig, MAX_PATH, argv[0]);
3589
if (strlen(defconfig)) {
3590
if (opt_debug)
3591
applog(LOG_DEBUG, "Using config %s", defconfig);
3592
parse_arg('c', defconfig);
3593
parse_cmdline(argc, argv);
3594
}
3595
}
3596
3597
if (!opt_n_threads)
3598
opt_n_threads = num_cpus;
3599
if (!opt_n_threads)
3600
opt_n_threads = 1;
3601
3602
if (opt_algo == ALGO_QUARK) {
3603
init_quarkhash_contexts();
3604
} else if(opt_algo == ALGO_CRYPTONIGHT || opt_algo == ALGO_CRYPTOLIGHT) {
3605
jsonrpc_2 = true;
3606
opt_extranonce = false;
3607
aes_ni_supported = has_aes_ni();
3608
if (!opt_quiet) {
3609
applog(LOG_INFO, "Using JSON-RPC 2.0");
3610
applog(LOG_INFO, "CPU Supports AES-NI: %s", aes_ni_supported ? "YES" : "NO");
3611
}
3612
} else if(opt_algo == ALGO_DECRED || opt_algo == ALGO_SIA) {
3613
have_gbt = false;
3614
} else if(opt_algo == ALGO_MINOTAURX) { // Activating MinX for GBT
3615
// applog(LOG_INFO, "Activating the BlockTemplate for MinotaurX");
3616
opt_minotaurx = true;
3617
}
3618
3619
if (!opt_benchmark && !rpc_url) {
3620
fprintf(stderr, "%s: no URL supplied\n", argv[0]);
3621
show_usage_and_exit(1);
3622
}
3623
3624
if (!rpc_userpass) {
3625
rpc_userpass = (char*) malloc(strlen(rpc_user) + strlen(rpc_pass) + 2);
3626
if (!rpc_userpass)
3627
return 1;
3628
sprintf(rpc_userpass, "%s:%s", rpc_user, rpc_pass);
3629
}
3630
3631
pthread_mutex_init(&stats_lock, NULL);
3632
pthread_mutex_init(&g_work_lock, NULL);
3633
pthread_mutex_init(&rpc2_job_lock, NULL);
3634
pthread_mutex_init(&rpc2_login_lock, NULL);
3635
pthread_mutex_init(&stratum.sock_lock, NULL);
3636
pthread_mutex_init(&stratum.work_lock, NULL);
3637
3638
flags = !opt_benchmark && strncmp(rpc_url, "https:", 6)
3639
? (CURL_GLOBAL_ALL & ~CURL_GLOBAL_SSL)
3640
: CURL_GLOBAL_ALL;
3641
if (curl_global_init(flags)) {
3642
applog(LOG_ERR, "CURL initialization failed");
3643
return 1;
3644
}
3645
3646
#ifndef WIN32
3647
if (opt_background) {
3648
i = fork();
3649
if (i < 0) exit(1);
3650
if (i > 0) exit(0);
3651
i = setsid();
3652
if (i < 0)
3653
applog(LOG_ERR, "setsid() failed (errno = %d)", errno);
3654
i = chdir("/");
3655
if (i < 0)
3656
applog(LOG_ERR, "chdir() failed (errno = %d)", errno);
3657
signal(SIGHUP, signal_handler);
3658
signal(SIGTERM, signal_handler);
3659
}
3660
/* Always catch Ctrl+C */
3661
signal(SIGINT, signal_handler);
3662
#else
3663
SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler, TRUE);
3664
if (opt_background) {
3665
HWND hcon = GetConsoleWindow();
3666
if (hcon) {
3667
// this method also hide parent command line window
3668
ShowWindow(hcon, SW_HIDE);
3669
} else {
3670
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
3671
CloseHandle(h);
3672
FreeConsole();
3673
}
3674
}
3675
if (opt_priority > 0) {
3676
DWORD prio = NORMAL_PRIORITY_CLASS;
3677
switch (opt_priority) {
3678
case 1:
3679
prio = BELOW_NORMAL_PRIORITY_CLASS;
3680
break;
3681
case 3:
3682
prio = ABOVE_NORMAL_PRIORITY_CLASS;
3683
break;
3684
case 4:
3685
prio = HIGH_PRIORITY_CLASS;
3686
break;
3687
case 5:
3688
prio = REALTIME_PRIORITY_CLASS;
3689
}
3690
SetPriorityClass(GetCurrentProcess(), prio);
3691
}
3692
#endif
3693
if (opt_affinity != -1) {
3694
if (!opt_quiet)
3695
applog(LOG_DEBUG, "Binding process to cpu mask %x", opt_affinity);
3696
affine_to_cpu_mask(-1, (unsigned long)opt_affinity);
3697
}
3698
3699
#ifdef HAVE_SYSLOG_H
3700
if (use_syslog)
3701
openlog("cpuminer", LOG_PID, LOG_USER);
3702
#endif
3703
3704
work_restart = (struct work_restart*) calloc(opt_n_threads, sizeof(*work_restart));
3705
if (!work_restart)
3706
return 1;
3707
3708
thr_info = (struct thr_info*) calloc(opt_n_threads + 4, sizeof(*thr));
3709
if (!thr_info)
3710
return 1;
3711
3712
thr_hashrates = (double *) calloc(opt_n_threads, sizeof(double));
3713
if (!thr_hashrates)
3714
return 1;
3715
3716
/* init workio thread info */
3717
work_thr_id = opt_n_threads;
3718
thr = &thr_info[work_thr_id];
3719
thr->id = work_thr_id;
3720
thr->q = tq_new();
3721
if (!thr->q)
3722
return 1;
3723
3724
if (rpc_pass && rpc_user)
3725
opt_stratum_stats = (strstr(rpc_pass, "stats") != NULL) || (strcmp(rpc_user, "benchmark") == 0);
3726
3727
/* start work I/O thread */
3728
if (thread_create(thr, workio_thread)) {
3729
applog(LOG_ERR, "work thread create failed");
3730
return 1;
3731
}
3732
3733
/* ESET-NOD32 Detects these 2 thread_create... */
3734
if (want_longpoll && !have_stratum) {
3735
/* init longpoll thread info */
3736
longpoll_thr_id = opt_n_threads + 1;
3737
thr = &thr_info[longpoll_thr_id];
3738
thr->id = longpoll_thr_id;
3739
thr->q = tq_new();
3740
if (!thr->q)
3741
return 1;
3742
3743
/* start longpoll thread */
3744
err = thread_create(thr, longpoll_thread);
3745
if (err) {
3746
applog(LOG_ERR, "long poll thread create failed");
3747
return 1;
3748
}
3749
}
3750
if (want_stratum) {
3751
/* init stratum thread info */
3752
stratum_thr_id = opt_n_threads + 2;
3753
thr = &thr_info[stratum_thr_id];
3754
thr->id = stratum_thr_id;
3755
thr->q = tq_new();
3756
if (!thr->q)
3757
return 1;
3758
3759
/* start stratum thread */
3760
err = thread_create(thr, stratum_thread);
3761
if (err) {
3762
applog(LOG_ERR, "stratum thread create failed");
3763
return 1;
3764
}
3765
if (have_stratum)
3766
tq_push(thr_info[stratum_thr_id].q, strdup(rpc_url));
3767
}
3768
3769
if (opt_api_listen) {
3770
/* api thread */
3771
api_thr_id = opt_n_threads + 3;
3772
thr = &thr_info[api_thr_id];
3773
thr->id = api_thr_id;
3774
thr->q = tq_new();
3775
if (!thr->q)
3776
return 1;
3777
err = thread_create(thr, api_thread);
3778
if (err) {
3779
applog(LOG_ERR, "api thread create failed");
3780
return 1;
3781
}
3782
}
3783
3784
/* start mining threads */
3785
for (i = 0; i < opt_n_threads; i++) {
3786
thr = &thr_info[i];
3787
3788
thr->id = i;
3789
thr->q = tq_new();
3790
if (!thr->q)
3791
return 1;
3792
3793
err = thread_create(thr, miner_thread);
3794
if (err) {
3795
applog(LOG_ERR, "thread %d create failed", i);
3796
return 1;
3797
}
3798
}
3799
3800
applog(LOG_INFO, "%d miner threads started, "
3801
"using '%s' algorithm.",
3802
opt_n_threads,
3803
algo_names[opt_algo]);
3804
3805
/* main loop - simply wait for workio thread to exit */
3806
pthread_join(thr_info[work_thr_id].pth, NULL);
3807
3808
applog(LOG_WARNING, "workio thread dead, exiting.");
3809
3810
return 0;
3811
}
3812
3813