Bug Summary

File:miner.c
Location:line 4313, column 7
Description:Branch condition evaluates to a garbage value

Annotated Source Code

1/*
2 * Copyright 2011-2013 Con Kolivas
3 * Copyright 2011-2013 Luke Dashjr
4 * Copyright 2012-2013 Andrew Smith
5 * Copyright 2010 Jeff Garzik
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 3 of the License, or (at your option)
10 * any later version. See COPYING for more details.
11 */
12
13#include "config.h"
14
15#ifdef HAVE_CURSES1
16#include <curses.h>
17#endif
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <stdbool.h>
23#include <stdint.h>
24#include <unistd.h>
25#include <sys/time.h>
26#include <time.h>
27#include <math.h>
28#include <stdarg.h>
29#include <assert.h>
30#include <signal.h>
31
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <dirent.h>
35
36#ifndef WIN32
37#include <sys/resource.h>
38#include <sys/socket.h>
39#else
40#include <winsock2.h>
41#endif
42#include <ccan/opt/opt.h>
43#include <jansson.h>
44#include <curl/curl.h>
45#include <libgen.h>
46#include <sha2.h>
47
48#include <blkmaker.h>
49#include <blkmaker_jansson.h>
50#include <blktemplate.h>
51
52#include "compat.h"
53#include "deviceapi.h"
54#include "miner.h"
55#include "findnonce.h"
56#include "adl.h"
57#include "driver-cpu.h"
58#include "driver-opencl.h"
59#include "bench_block.h"
60#include "scrypt.h"
61#ifdef USE_AVALON1
62 #include "driver-avalon.h"
63#endif
64
65#ifdef USE_X65001
66#include "ft232r.h"
67#endif
68
69#if defined(unix1)
70 #include <errno(*__errno_location ()).h>
71 #include <fcntl.h>
72 #include <sys/wait.h>
73#endif
74
75#ifdef USE_SCRYPT1
76#include "scrypt.h"
77#endif
78
79#if defined(USE_AVALON1) || defined(USE_BITFORCE1) || defined(USE_ICARUS1) || defined(USE_MODMINER1) || defined(USE_X65001) || defined(USE_ZTEX1)
80# define USE_FPGA
81# define USE_FPGA_SERIAL
82#endif
83
84struct strategies strategies[] = {
85 { "Failover" },
86 { "Round Robin" },
87 { "Rotate" },
88 { "Load Balance" },
89 { "Balance" },
90};
91
92static char packagename[256];
93
94bool_Bool opt_protocol;
95static bool_Bool opt_benchmark;
96static bool_Bool want_longpoll = true1;
97static bool_Bool want_gbt = true1;
98static bool_Bool want_getwork = true1;
99#if BLKMAKER_VERSION(4L) > 1
100struct _cbscript_t {
101 char *data;
102 size_t sz;
103};
104static struct _cbscript_t opt_coinbase_script;
105static uint32_t template_nonce;
106#endif
107#if BLKMAKER_VERSION(4L) < 1
108const
109#endif
110char *opt_coinbase_sig;
111char *request_target_str;
112float request_pdiff = 1.0;
113double request_bdiff;
114static bool_Bool want_stratum = true1;
115bool_Bool have_longpoll;
116int opt_skip_checks;
117bool_Bool want_per_device_stats;
118bool_Bool use_syslog;
119bool_Bool opt_quiet_work_updates;
120bool_Bool opt_quiet;
121bool_Bool opt_realquiet;
122bool_Bool opt_loginput;
123bool_Bool opt_compact;
124bool_Bool opt_show_procs;
125const int opt_cutofftemp = 95;
126int opt_hysteresis = 3;
127static int opt_retries = -1;
128int opt_fail_pause = 5;
129int opt_log_interval = 5;
130int opt_queue = 1;
131int opt_scantime = 60;
132int opt_expiry = 120;
133int opt_expiry_lp = 3600;
134int opt_bench_algo = -1;
135static const bool_Bool opt_time = true1;
136unsigned long long global_hashrate;
137
138#ifdef HAVE_OPENCL1
139int opt_dynamic_interval = 7;
140int nDevs;
141int opt_g_threads = -1;
142int gpu_threads;
143#endif
144#ifdef USE_SCRYPT1
145static char detect_algo = 1;
146bool_Bool opt_scrypt;
147#else
148static char detect_algo;
149#endif
150bool_Bool opt_restart = true1;
151static bool_Bool opt_nogpu;
152
153struct list_head scan_devices;
154bool_Bool opt_force_dev_init;
155static signed int devices_enabled;
156static bool_Bool opt_removedisabled;
157int total_devices;
158struct cgpu_info **devices;
159bool_Bool have_opencl;
160int opt_n_threads = -1;
161int mining_threads;
162int num_processors;
163#ifdef HAVE_CURSES1
164bool_Bool use_curses = true1;
165#else
166bool_Bool use_curses;
167#endif
168static bool_Bool opt_submit_stale = true1;
169static int opt_shares;
170static int opt_submit_threads = 0x40;
171bool_Bool opt_fail_only;
172bool_Bool opt_autofan;
173bool_Bool opt_autoengine;
174bool_Bool opt_noadl;
175char *opt_api_allow = NULL((void*)0);
176char *opt_api_groups;
177char *opt_api_description = PACKAGE_STRING"bfgminer 3.0.0";
178int opt_api_port = 4028;
179bool_Bool opt_api_listen;
180bool_Bool opt_api_network;
181bool_Bool opt_delaynet;
182bool_Bool opt_disable_pool;
183char *opt_icarus_options = NULL((void*)0);
184char *opt_icarus_timing = NULL((void*)0);
185bool_Bool opt_worktime;
186#ifdef USE_AVALON1
187char *opt_avalon_options = NULL((void*)0);
188#endif
189
190char *opt_kernel_path;
191char *cgminer_path;
192
193#if defined(USE_BITFORCE1)
194bool_Bool opt_bfl_noncerange;
195#endif
196#define QUIET(opt_quiet || opt_realquiet) (opt_quiet || opt_realquiet)
197
198struct thr_info *thr_info;
199static int gwsched_thr_id;
200static int stage_thr_id;
201static int watchpool_thr_id;
202static int watchdog_thr_id;
203#ifdef HAVE_CURSES1
204static int input_thr_id;
205#endif
206int gpur_thr_id;
207static int api_thr_id;
208static int total_threads;
209
210pthread_mutex_t hash_lock;
211static pthread_mutex_t qd_lock;
212static pthread_mutex_t *stgd_lock;
213pthread_mutex_t console_lock;
214pthread_mutex_t ch_lock;
215static pthread_rwlock_t blk_lock;
216static pthread_mutex_t sshare_lock;
217
218pthread_rwlock_t netacc_lock;
219
220static pthread_mutex_t lp_lock;
221static pthread_cond_t lp_cond;
222
223pthread_cond_t gws_cond;
224
225bool_Bool shutting_down;
226
227double total_mhashes_done;
228static struct timeval total_tv_start, total_tv_end;
229static struct timeval miner_started;
230
231pthread_mutex_t control_lock;
232pthread_mutex_t stats_lock;
233
234static pthread_mutex_t submitting_lock;
235static int total_submitting;
236static struct list_head submit_waiting;
237notifier_t submit_waiting_notifier;
238
239int hw_errors;
240int total_accepted, total_rejected, total_diff1;
241int total_getworks, total_stale, total_discarded;
242uint64_t total_bytes_xfer;
243double total_diff_accepted, total_diff_rejected, total_diff_stale;
244static int staged_rollable;
245unsigned int new_blocks;
246unsigned int found_blocks;
247
248unsigned int local_work;
249unsigned int total_go, total_ro;
250
251struct pool **pools;
252static struct pool *currentpool = NULL((void*)0);
253
254int total_pools, enabled_pools;
255enum pool_strategy pool_strategy = POOL_FAILOVER;
256int opt_rotate_period;
257static int total_urls, total_users, total_passes;
258
259static
260#ifndef HAVE_CURSES1
261const
262#endif
263bool_Bool curses_active;
264
265static char current_block[40];
266static char *current_hash;
267static uint32_t current_block_id;
268char *current_fullhash;
269static char datestamp[40];
270static char blocktime[32];
271struct timeval block_timeval;
272static char best_share[8] = "0";
273double current_diff;
274static char block_diff[8];
275static char net_hashrate[10];
276uint64_t best_diff = 0;
277
278static bool_Bool known_blkheight_current;
279static uint32_t known_blkheight;
280static uint32_t known_blkheight_blkid;
281
282struct block {
283 char hash[40];
284 UT_hash_handle hh;
285 int block_no;
286};
287
288static struct block *blocks = NULL((void*)0);
289
290
291int swork_id;
292
293/* For creating a hash database of stratum shares submitted that have not had
294 * a response yet */
295struct stratum_share {
296 UT_hash_handle hh;
297 bool_Bool block;
298 struct work *work;
299 int id;
300 time_t sshare_time;
301};
302
303static struct stratum_share *stratum_shares = NULL((void*)0);
304
305char *opt_socks_proxy = NULL((void*)0);
306
307static const char def_conf[] = "bfgminer.conf";
308static bool_Bool config_loaded;
309static int include_count;
310#define JSON_INCLUDE_CONF"include" "include"
311#define JSON_LOAD_ERROR"JSON decode of file '%s' failed\n %s" "JSON decode of file '%s' failed\n %s"
312#define JSON_LOAD_ERROR_LENstrlen("JSON decode of file '%s' failed\n %s") strlen(JSON_LOAD_ERROR"JSON decode of file '%s' failed\n %s")
313#define JSON_MAX_DEPTH10 10
314#define JSON_MAX_DEPTH_ERR"Too many levels of JSON includes (limit 10) or a loop" "Too many levels of JSON includes (limit 10) or a loop"
315
316#if defined(unix1)
317 static char *opt_stderr_cmd = NULL((void*)0);
318 static int forkpid;
319#endif // defined(unix)
320
321struct sigaction termhandler, inthandler;
322
323struct thread_q *getq;
324
325static int total_work;
326struct work *staged_work = NULL((void*)0);
327
328struct schedtime {
329 bool_Bool enable;
330 struct tm tm;
331};
332
333struct schedtime schedstart;
334struct schedtime schedstop;
335bool_Bool sched_paused;
336
337static bool_Bool time_before(struct tm *tm1, struct tm *tm2)
338{
339 if (tm1->tm_hour < tm2->tm_hour)
340 return true1;
341 if (tm1->tm_hour == tm2->tm_hour && tm1->tm_min < tm2->tm_min)
342 return true1;
343 return false0;
344}
345
346static bool_Bool should_run(void)
347{
348 struct timeval tv;
349 struct tm tm;
350 bool_Bool within_range;
351
352 if (!schedstart.enable && !schedstop.enable)
353 return true1;
354
355 gettimeofday(&tv, NULL((void*)0));
356 localtime_r(&tv.tv_sec, &tm);
357
358 // NOTE: This is delicately balanced so that should_run is always false if schedstart==schedstop
359 if (time_before(&schedstop.tm, &schedstart.tm))
360 within_range = (time_before(&tm, &schedstop.tm) || !time_before(&tm, &schedstart.tm));
361 else
362 within_range = (time_before(&tm, &schedstop.tm) && !time_before(&tm, &schedstart.tm));
363
364 if (within_range && !schedstop.enable)
365 /* This is a once off event with no stop time set */
366 schedstart.enable = false0;
367
368 return within_range;
369}
370
371void get_datestamp(char *f, struct timeval *tv)
372{
373 struct tm _tm;
374 struct tm *tm = &_tm;
375
376 localtime_r(&tv->tv_sec, tm);
377 sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d]",
378 tm->tm_year + 1900,
379 tm->tm_mon + 1,
380 tm->tm_mday,
381 tm->tm_hour,
382 tm->tm_min,
383 tm->tm_sec);
384}
385
386void get_timestamp(char *f, struct timeval *tv)
387{
388 struct tm _tm;
389 struct tm *tm = &_tm;
390
391 localtime_r(&tv->tv_sec, tm);
392 sprintf(f, "[%02d:%02d:%02d]",
393 tm->tm_hour,
394 tm->tm_min,
395 tm->tm_sec);
396}
397
398static void applog_and_exit(const char *fmt, ...)
399{
400 va_list ap;
401
402 va_start(ap, fmt)__builtin_va_start(ap, fmt);
403 vapplog(LOG_ERR3, fmt, ap);
404 va_end(ap)__builtin_va_end(ap);
405 exit(1);
406}
407
408static pthread_mutex_t sharelog_lock;
409static FILE *sharelog_file = NULL((void*)0);
410
411static void sharelog(const char*disposition, const struct work*work)
412{
413 char *target, *hash, *data;
414 struct cgpu_info *cgpu;
415 unsigned long int t;
416 struct pool *pool;
417 int thr_id, rv;
418 char s[1024];
419 size_t ret;
420
421 if (!sharelog_file)
422 return;
423
424 thr_id = work->thr_id;
425 cgpu = thr_info[thr_id].cgpu;
426 pool = work->pool;
427 t = (unsigned long int)(work->tv_work_found.tv_sec);
428 target = bin2hex(work->target, sizeof(work->target));
429 hash = bin2hex(work->hash, sizeof(work->hash));
430 data = bin2hex(work->data, sizeof(work->data));
431
432 // timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
433 rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->proc_repr_ns, thr_id, hash, data);
434 free(target);
435 free(hash);
436 free(data);
437 if (rv >= (int)(sizeof(s)))
438 s[sizeof(s) - 1] = '\0';
439 else if (rv < 0) {
440 applog(LOG_ERR3, "sharelog printf error");
441 return;
442 }
443
444 mutex_lock(&sharelog_lock);
445 ret = fwrite(s, rv, 1, sharelog_file);
446 fflush(sharelog_file);
447 mutex_unlock(&sharelog_lock);
448 if (ret != 1)
449 applog(LOG_ERR3, "sharelog fwrite error");
450}
451
452static char *getwork_req = "{\"method\": \"getwork\", \"params\": [], \"id\":0}\n";
453
454/* Return value is ignored if not called from add_pool_details */
455struct pool *add_pool(void)
456{
457 struct pool *pool;
458
459 pool = calloc(sizeof(struct pool), 1);
460 if (!pool)
461 quit(1, "Failed to malloc pool in add_pool");
462 pool->pool_no = pool->prio = total_pools;
463 mutex_init(&pool->last_work_lock);
464 mutex_init(&pool->pool_lock);
465 if (unlikely(pthread_cond_init(&pool->cr_cond, NULL))(pthread_cond_init(&pool->cr_cond, ((void*)0))))
466 quit(1, "Failed to pthread_cond_init in add_pool");
467 mutex_init(&pool->stratum_lock);
468 INIT_LIST_HEAD(&pool->curlring)do { (&pool->curlring)->next = (&pool->curlring
); (&pool->curlring)->prev = (&pool->curlring
); } while (0)
;
469 pool->swork.transparency_time = (time_t)-1;
470
471 /* Make sure the pool doesn't think we've been idle since time 0 */
472 pool->tv_idle.tv_sec = ~0UL;
473
474 pool->rpc_proxy = NULL((void*)0);
475
476 pool->sock = INVSOCK-1;
477 pool->lp_socket = CURL_SOCKET_BAD-1;
478
479 pools = realloc(pools, sizeof(struct pool *) * (total_pools + 2));
480 pools[total_pools++] = pool;
481
482 return pool;
483}
484
485/* Pool variant of test and set */
486static bool_Bool pool_tset(struct pool *pool, bool_Bool *var)
487{
488 bool_Bool ret;
489
490 mutex_lock(&pool->pool_lock);
491 ret = *var;
492 *var = true1;
493 mutex_unlock(&pool->pool_lock);
494 return ret;
495}
496
497bool_Bool pool_tclear(struct pool *pool, bool_Bool *var)
498{
499 bool_Bool ret;
500
501 mutex_lock(&pool->pool_lock);
502 ret = *var;
503 *var = false0;
504 mutex_unlock(&pool->pool_lock);
505 return ret;
506}
507
508struct pool *current_pool(void)
509{
510 struct pool *pool;
511
512 mutex_lock(&control_lock);
513 pool = currentpool;
514 mutex_unlock(&control_lock);
515 return pool;
516}
517
518char *set_int_range(const char *arg, int *i, int min, int max)
519{
520 char *err = opt_set_intval(arg, i);
521
522 if (err)
523 return err;
524
525 if (*i < min || *i > max)
526 return "Value out of range";
527
528 return NULL((void*)0);
529}
530
531static char *set_int_0_to_9999(const char *arg, int *i)
532{
533 return set_int_range(arg, i, 0, 9999);
534}
535
536static char *set_int_1_to_65535(const char *arg, int *i)
537{
538 return set_int_range(arg, i, 1, 65535);
539}
540
541static char *set_int_0_to_10(const char *arg, int *i)
542{
543 return set_int_range(arg, i, 0, 10);
544}
545
546static char *set_int_1_to_10(const char *arg, int *i)
547{
548 return set_int_range(arg, i, 1, 10);
549}
550
551char *set_strdup(const char *arg, char **p)
552{
553 *p = strdup((char *)arg);
554 return NULL((void*)0);
555}
556
557#if BLKMAKER_VERSION(4L) > 1
558static char *set_b58addr(const char *arg, struct _cbscript_t *p)
559{
560 size_t scriptsz = blkmk_address_to_script(NULL((void*)0), 0, arg);
561 if (!scriptsz)
562 return "Invalid address";
563 char *script = malloc(scriptsz);
564 if (blkmk_address_to_script(script, scriptsz, arg) != scriptsz) {
565 free(script);
566 return "Failed to convert address to script";
567 }
568 p->data = script;
569 p->sz = scriptsz;
570 return NULL((void*)0);
571}
572#endif
573
574static void bdiff_target_leadzero(unsigned char *target, double diff);
575
576char *set_request_diff(const char *arg, float *p)
577{
578 unsigned char target[32];
579 char *e = opt_set_floatval(arg, p);
580 if (e)
581 return e;
582
583 request_bdiff = (double)*p * 0.9999847412109375;
584 bdiff_target_leadzero(target, request_bdiff);
585 request_target_str = bin2hex(target, 32);
586
587 return NULL((void*)0);
588}
589
590#ifdef HAVE_LIBUDEV1
591#include <libudev.h>
592#endif
593
594static
595char* add_serial_all(char*arg, char*p) {
596#ifdef HAVE_LIBUDEV1
597
598 struct udev *udev = udev_new();
599 struct udev_enumerate *enumerate = udev_enumerate_new(udev);
600 struct udev_list_entry *list_entry;
601
602 udev_enumerate_add_match_subsystem(enumerate, "tty");
603 udev_enumerate_add_match_property(enumerate, "ID_SERIAL", "*");
604 udev_enumerate_scan_devices(enumerate);
605 udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate))for (list_entry = udev_enumerate_get_list_entry(enumerate); list_entry
!= ((void*)0); list_entry = udev_list_entry_get_next(list_entry
))
{
606 struct udev_device *device = udev_device_new_from_syspath(
607 udev_enumerate_get_udev(enumerate),
608 udev_list_entry_get_name(list_entry)
609 );
610 if (!device)
611 continue;
612
613 const char *devpath = udev_device_get_devnode(device);
614 if (devpath) {
615 size_t pLen = p - arg;
616 size_t dLen = strlen(devpath) + 1;
617 char dev[dLen + pLen];
618 memcpy(dev, arg, pLen);
619 memcpy(&dev[pLen], devpath, dLen);
620 applog(LOG_DEBUG7, "scan-serial: libudev all-adding %s", dev);
621 string_elist_add(dev, &scan_devices);
622 }
623
624 udev_device_unref(device);
625 }
626 udev_enumerate_unref(enumerate);
627 udev_unref(udev);
628 return NULL((void*)0);
629
630#elif defined(WIN32)
631
632 size_t bufLen = 0x10; // temp!
633tryagain: ;
634 char buf[bufLen];
635 if (!QueryDosDevice(NULL((void*)0), buf, bufLen)) {
636 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
637 bufLen *= 2;
638 applog(LOG_DEBUG7, "scan-serial: QueryDosDevice returned insufficent buffer error; enlarging to %lx", (unsigned long)bufLen);
639 goto tryagain;
640 }
641 return "scan-serial: Error occurred trying to enumerate COM ports with QueryDosDevice";
642 }
643 size_t tLen = p - arg;
644 char dev[12 + tLen];
645 memcpy(dev, arg, tLen);
646 memcpy(&dev[tLen], "\\\\.\\", 4);
647 char *devp = &dev[tLen + 4];
648 for (char *t = buf; *t; t += tLen) {
649 tLen = strlen(t) + 1;
650 if (strncmp("COM", t, 3))
651 continue;
652 memcpy(devp, t, tLen);
653 applog(LOG_DEBUG7, "scan-serial: QueryDosDevice all-adding %s", dev);
654 string_elist_add(dev, &scan_devices);
655 }
656 return NULL((void*)0);
657
658#else
659
660 DIR *D;
661 struct dirent *de;
662 const char devdir[] = "/dev";
663 const size_t devdirlen = sizeof(devdir) - 1;
664 char devpath[sizeof(devdir) + NAME_MAX255];
665 char *devfile = devpath + devdirlen + 1;
666
667 D = opendir(devdir);
668 if (!D)
669 return "scan-serial 'all' is not supported on this platform";
670 memcpy(devpath, devdir, devdirlen);
671 devpath[devdirlen] = '/';
672 while ( (de = readdir(D)) ) {
673 if (strncmp(de->d_name, "tty", 3))
674 continue;
675 if (strncmp(&de->d_name[3], "USB", 3) && strncmp(&de->d_name[3], "ACM", 3))
676 continue;
677
678 strcpy(devfile, de->d_name);
679 applog(LOG_DEBUG7, "scan-serial: /dev glob all-adding %s", devpath);
680 string_elist_add(devpath, &scan_devices);
681 }
682 closedir(D);
683
684 return NULL((void*)0);
685
686#endif
687}
688
689#ifdef USE_FPGA_SERIAL
690static char *add_serial(char *arg)
691{
692 char *p = strchr(arg, ':');
693 if (p)
694 ++p;
695 else
696 p = arg;
697 if (!strcasecmp(p, "all")) {
698 return add_serial_all(arg, p);
699 }
700
701 string_elist_add(arg, &scan_devices);
702 return NULL((void*)0);
703}
704#endif
705
706static char *set_devices(char *arg)
707{
708 int i = strtol(arg, &arg, 0);
709
710 if (*arg) {
711 if (*arg == '?') {
712 devices_enabled = -1;
713 return NULL((void*)0);
714 }
715 return "Invalid device number";
716 }
717
718 if (i < 0 || i >= (int)(sizeof(devices_enabled) * 8) - 1)
719 return "Invalid device number";
720 devices_enabled |= 1 << i;
721 return NULL((void*)0);
722}
723
724static char *set_balance(enum pool_strategy *strategy)
725{
726 *strategy = POOL_BALANCE;
727 return NULL((void*)0);
728}
729
730static char *set_loadbalance(enum pool_strategy *strategy)
731{
732 *strategy = POOL_LOADBALANCE;
733 return NULL((void*)0);
734}
735
736static char *set_rotate(const char *arg, int *i)
737{
738 pool_strategy = POOL_ROTATE;
739 return set_int_range(arg, i, 0, 9999);
740}
741
742static char *set_rr(enum pool_strategy *strategy)
743{
744 *strategy = POOL_ROUNDROBIN;
745 return NULL((void*)0);
746}
747
748/* Detect that url is for a stratum protocol either via the presence of
749 * stratum+tcp or by detecting a stratum server response */
750bool_Bool detect_stratum(struct pool *pool, char *url)
751{
752 if (!extract_sockaddr(pool, url))
753 return false0;
754
755 if (!strncasecmp(url, "stratum+tcp://", 14)) {
756 pool->rpc_url = strdup(url);
757 pool->has_stratum = true1;
758 pool->stratum_url = pool->sockaddr_url;
759 return true1;
760 }
761
762 return false0;
763}
764
765static char *set_url(char *arg)
766{
767 struct pool *pool;
768
769 total_urls++;
770 if (total_urls > total_pools)
771 add_pool();
772 pool = pools[total_urls - 1];
773
774 if (detect_stratum(pool, arg))
775 return NULL((void*)0);
776
777 opt_set_charp(arg, &pool->rpc_url);
778 if (strncmp(arg, "http://", 7) &&
779 strncmp(arg, "https://", 8)) {
780 char *httpinput;
781
782 httpinput = malloc(255);
783 if (!httpinput)
784 quit(1, "Failed to malloc httpinput");
785 strcpy(httpinput, "http://");
786 strncat(httpinput, arg, 248);
787 pool->rpc_url = httpinput;
788 }
789
790 return NULL((void*)0);
791}
792
793static char *set_user(const char *arg)
794{
795 struct pool *pool;
796
797 total_users++;
798 if (total_users > total_pools)
799 add_pool();
800
801 pool = pools[total_users - 1];
802 opt_set_charp(arg, &pool->rpc_user);
803
804 return NULL((void*)0);
805}
806
807static char *set_pass(const char *arg)
808{
809 struct pool *pool;
810
811 total_passes++;
812 if (total_passes > total_pools)
813 add_pool();
814
815 pool = pools[total_passes - 1];
816 opt_set_charp(arg, &pool->rpc_pass);
817
818 return NULL((void*)0);
819}
820
821static char *set_userpass(const char *arg)
822{
823 struct pool *pool;
824 char *updup;
825
826 if (total_users != total_passes)
827 return "User + pass options must be balanced before userpass";
828 ++total_users;
829 ++total_passes;
830 if (total_users > total_pools)
831 add_pool();
832
833 pool = pools[total_users - 1];
834 updup = strdup(arg);
835 opt_set_charp(arg, &pool->rpc_userpass);
836 pool->rpc_user = strtok(updup, ":");
837 if (!pool->rpc_user)
838 return "Failed to find : delimited user info";
839 pool->rpc_pass = strtok(NULL((void*)0), ":");
840 if (!pool->rpc_pass)
841 pool->rpc_pass = "";
842
843 return NULL((void*)0);
844}
845
846static char *set_pool_priority(const char *arg)
847{
848 struct pool *pool;
849
850 if (!total_pools)
851 return "Usage of --pool-priority before pools are defined does not make sense";
852
853 pool = pools[total_pools - 1];
854 opt_set_intval(arg, &pool->prio);
855
856 return NULL((void*)0);
857}
858
859static char *set_pool_proxy(const char *arg)
860{
861 struct pool *pool;
862
863 if (!total_pools)
864 return "Usage of --pool-proxy before pools are defined does not make sense";
865
866 if (!our_curl_supports_proxy_uris())
867 return "Your installed cURL library does not support proxy URIs. At least version 7.21.7 is required.";
868
869 pool = pools[total_pools - 1];
870 opt_set_charp(arg, &pool->rpc_proxy);
871
872 return NULL((void*)0);
873}
874
875static char *set_pool_force_rollntime(const char *arg)
876{
877 struct pool *pool;
878
879 if (!total_pools)
880 return "Usage of --force-rollntime before pools are defined does not make sense";
881
882 pool = pools[total_pools - 1];
883 opt_set_intval(arg, &pool->force_rollntime);
884
885 return NULL((void*)0);
886}
887
888static char *enable_debug(bool_Bool *flag)
889{
890 *flag = true1;
891 opt_debug_console = true1;
892 /* Turn on verbose output, too. */
893 opt_log_output = true1;
894 return NULL((void*)0);
895}
896
897static char *set_schedtime(const char *arg, struct schedtime *st)
898{
899 if (sscanf(arg, "%d:%d", &st->tm.tm_hour, &st->tm.tm_min) != 2)
900 {
901 if (strcasecmp(arg, "now"))
902 return "Invalid time set, should be HH:MM";
903 } else
904 schedstop.tm.tm_sec = 0;
905 if (st->tm.tm_hour > 23 || st->tm.tm_min > 59 || st->tm.tm_hour < 0 || st->tm.tm_min < 0)
906 return "Invalid time set.";
907 st->enable = true1;
908 return NULL((void*)0);
909}
910
911static char* set_sharelog(char *arg)
912{
913 char *r = "";
914 long int i = strtol(arg, &r, 10);
915
916 if ((!*r) && i >= 0 && i <= INT_MAX2147483647) {
917 sharelog_file = fdopen((int)i, "a");
918 if (!sharelog_file)
919 applog(LOG_ERR3, "Failed to open fd %u for share log", (unsigned int)i);
920 } else if (!strcmp(arg, "-")) {
921 sharelog_file = stdoutstdout;
922 if (!sharelog_file)
923 applog(LOG_ERR3, "Standard output missing for share log");
924 } else {
925 sharelog_file = fopen(arg, "a");
926 if (!sharelog_file)
927 applog(LOG_ERR3, "Failed to open %s for share log", arg);
928 }
929
930 return NULL((void*)0);
931}
932
933static char *temp_cutoff_str = "";
934static char *temp_target_str = "";
935
936char *set_temp_cutoff(char *arg)
937{
938 int val;
939
940 if (!(arg && arg[0]))
941 return "Invalid parameters for set temp cutoff";
942 val = atoi(arg);
943 if (val < 0 || val > 200)
944 return "Invalid value passed to set temp cutoff";
945 temp_cutoff_str = arg;
946
947 return NULL((void*)0);
948}
949
950char *set_temp_target(char *arg)
951{
952 int val;
953
954 if (!(arg && arg[0]))
955 return "Invalid parameters for set temp target";
956 val = atoi(arg);
957 if (val < 0 || val > 200)
958 return "Invalid value passed to set temp target";
959 temp_target_str = arg;
960
961 return NULL((void*)0);
962}
963
964// For a single element string, this always returns the number (for all calls)
965// For multi-element strings, it returns each element as a number in order, and 0 when there are no more
966static int temp_strtok(char *base, char **n)
967{
968 char *i = *n;
969 char *p = strchr(i, ',');
970 if (p) {
971 p[0] = '\0';
972 *n = &p[1];
973 }
974 else
975 if (base != i)
976 *n = strchr(i, '\0');
977 return atoi(i);
978}
979
980static void load_temp_config()
981{
982 int i, val = 0, target_off;
983 char *cutoff_n, *target_n;
984 struct cgpu_info *cgpu;
985
986 cutoff_n = temp_cutoff_str;
987 target_n = temp_target_str;
988
989 for (i = 0; i < total_devices; ++i) {
990 cgpu = devices[i];
991
992 // cutoff default may be specified by driver during probe; otherwise, opt_cutofftemp (const)
993 if (!cgpu->cutofftemp)
994 cgpu->cutofftemp = opt_cutofftemp;
995
996 // target default may be specified by driver, and is moved with offset; otherwise, offset minus 6
997 if (cgpu->targettemp)
998 target_off = cgpu->targettemp - cgpu->cutofftemp;
999 else
1000 target_off = -6;
1001
1002 val = temp_strtok(temp_cutoff_str, &cutoff_n);
1003 if (val < 0 || val > 200)
1004 quit(1, "Invalid value passed to set temp cutoff");
1005 if (val)
1006 cgpu->cutofftemp = val;
1007
1008 val = temp_strtok(temp_target_str, &target_n);
1009 if (val < 0 || val > 200)
1010 quit(1, "Invalid value passed to set temp target");
1011 if (val)
1012 cgpu->targettemp = val;
1013 else
1014 cgpu->targettemp = cgpu->cutofftemp + target_off;
1015
1016 applog(LOG_DEBUG7, "%"PRIprepr"-6s"": Set temperature config: target=%d cutoff=%d",
1017 cgpu->proc_repr,
1018 cgpu->targettemp, cgpu->cutofftemp);
1019 }
1020 if (cutoff_n != temp_cutoff_str && cutoff_n[0])
1021 quit(1, "Too many values passed to set temp cutoff");
1022 if (target_n != temp_target_str && target_n[0])
1023 quit(1, "Too many values passed to set temp target");
1024}
1025
1026static char *set_api_allow(const char *arg)
1027{
1028 opt_set_charp(arg, &opt_api_allow);
1029
1030 return NULL((void*)0);
1031}
1032
1033static char *set_api_groups(const char *arg)
1034{
1035 opt_set_charp(arg, &opt_api_groups);
1036
1037 return NULL((void*)0);
1038}
1039
1040static char *set_api_description(const char *arg)
1041{
1042 opt_set_charp(arg, &opt_api_description);
1043
1044 return NULL((void*)0);
1045}
1046
1047#ifdef USE_ICARUS1
1048static char *set_icarus_options(const char *arg)
1049{
1050 opt_set_charp(arg, &opt_icarus_options);
1051
1052 return NULL((void*)0);
1053}
1054
1055static char *set_icarus_timing(const char *arg)
1056{
1057 opt_set_charp(arg, &opt_icarus_timing);
1058
1059 return NULL((void*)0);
1060}
1061#endif
1062
1063#ifdef USE_AVALON1
1064static char *set_avalon_options(const char *arg)
1065{
1066 opt_set_charp(arg, &opt_avalon_options);
1067
1068 return NULL((void*)0);
1069}
1070#endif
1071
1072__maybe_unused__attribute__((unused))
1073static char *set_null(const char __maybe_unused__attribute__((unused)) *arg)
1074{
1075 return NULL((void*)0);
1076}
1077
1078/* These options are available from config file or commandline */
1079static struct opt_table opt_config_table[] = {
1080#ifdef WANT_CPUMINE1
1081 OPT_WITH_ARG("--algo|-a",{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1082 set_algo, show_algo, &opt_algo,{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1083 "Specify sha256 implementation for CPU mining:\n"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1084 "\tauto\t\tBenchmark at startup and pick fastest algorithm"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1085 "\n\tc\t\tLinux kernel sha256, implemented in C"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1086#ifdef WANT_SSE2_4WAY{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1087 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1088#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1089#ifdef WANT_VIA_PADLOCK{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1090 "\n\tvia\t\tVIA padlock implementation"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1091#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1092 "\n\tcryptopp\tCrypto++ C/C++ implementation"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1093#ifdef WANT_CRYPTOPP_ASM32{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1094 "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1095#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1096#ifdef WANT_X8632_SSE2{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1097 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1098#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1099#ifdef WANT_X8664_SSE2{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1100 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1101#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1102#ifdef WANT_X8664_SSE4{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1103 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1104#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1105#ifdef WANT_ALTIVEC_4WAY{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1106 "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1107#endif{ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
1108 ){ ("--algo|-a"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_algo))))))))), ((void (*)(char buf[],
const void *))(((show_algo)))), { (&opt_algo) }, ("Specify sha256 implementation for CPU mining:\n"
"\tauto\t\tBenchmark at startup and pick fastest algorithm" "\n\tc\t\tLinux kernel sha256, implemented in C"
ifdef 1 "\n\t4way\t\ttcatm's 4-way SSE2 implementation"endif ifdef
1 "\n\tvia\t\tVIA padlock implementation"endif "\n\tcryptopp\tCrypto++ C/C++ implementation"
ifdef "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
endif ifdef 1 "\n\tsse2_32\t\tSSE2 32 bit implementation for i386 machines"
endif ifdef WANT_X8664_SSE2 "\n\tsse2_64\t\tSSE2 64 bit implementation for x86_64 machines"
endif ifdef WANT_X8664_SSE4 "\n\tsse4_64\t\tSSE4.1 64 bit implementation for x86_64 machines"
endif ifdef WANT_ALTIVEC_4WAY "\n\taltivec_4way\tAltivec implementation for PowerPC G4 and G5 machines"
endif) }
,
1109#endif
1110 OPT_WITH_ARG("--api-allow",{ ("--api-allow"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_api_allow))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"
) }
1111 set_api_allow, NULL, NULL,{ ("--api-allow"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_api_allow))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"
) }
1112 "Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"){ ("--api-allow"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_api_allow))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"
) }
,
1113 OPT_WITH_ARG("--api-description",{ ("--api-description"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_api_description))))))))), (
(void (*)(char buf[], const void *))(((((void*)0))))), { (((void
*)0)) }, ("Description placed in the API status header, default: BFGMiner version"
) }
1114 set_api_description, NULL, NULL,{ ("--api-description"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_api_description))))))))), (
(void (*)(char buf[], const void *))(((((void*)0))))), { (((void
*)0)) }, ("Description placed in the API status header, default: BFGMiner version"
) }
1115 "Description placed in the API status header, default: BFGMiner version"){ ("--api-description"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_api_description))))))))), (
(void (*)(char buf[], const void *))(((((void*)0))))), { (((void
*)0)) }, ("Description placed in the API status header, default: BFGMiner version"
) }
,
1116 OPT_WITH_ARG("--api-groups",{ ("--api-groups"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_api_groups))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"
) }
1117 set_api_groups, NULL, NULL,{ ("--api-groups"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_api_groups))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"
) }
1118 "API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"){ ("--api-groups"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_api_groups))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"
) }
,
1119 OPT_WITHOUT_ARG("--api-listen",{ ("--api-listen"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_api_listen) }, ("Enable API, default: disabled"
) }
1120 opt_set_bool, &opt_api_listen,{ ("--api-listen"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_api_listen) }, ("Enable API, default: disabled"
) }
1121 "Enable API, default: disabled"){ ("--api-listen"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_api_listen) }, ("Enable API, default: disabled"
) }
,
1122 OPT_WITHOUT_ARG("--api-network",{ ("--api-network"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_api_network) }, ("Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"
) }
1123 opt_set_bool, &opt_api_network,{ ("--api-network"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_api_network) }, ("Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"
) }
1124 "Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"){ ("--api-network"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_api_network) }, ("Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"
) }
,
1125 OPT_WITH_ARG("--api-port",{ ("--api-port"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_1_to_65535))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_api_port
) }, ("Port number of miner API") }
1126 set_int_1_to_65535, opt_show_intval, &opt_api_port,{ ("--api-port"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_1_to_65535))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_api_port
) }, ("Port number of miner API") }
1127 "Port number of miner API"){ ("--api-port"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_1_to_65535))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_api_port
) }, ("Port number of miner API") }
,
1128#ifdef HAVE_ADL1
1129 OPT_WITHOUT_ARG("--auto-fan",{ ("--auto-fan"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autofan) }, ("Automatically adjust all GPU fan speeds to maintain a target temperature"
) }
1130 opt_set_bool, &opt_autofan,{ ("--auto-fan"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autofan) }, ("Automatically adjust all GPU fan speeds to maintain a target temperature"
) }
1131 "Automatically adjust all GPU fan speeds to maintain a target temperature"){ ("--auto-fan"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autofan) }, ("Automatically adjust all GPU fan speeds to maintain a target temperature"
) }
,
1132 OPT_WITHOUT_ARG("--auto-gpu",{ ("--auto-gpu"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autoengine) }, ("Automatically adjust all GPU engine clock speeds to maintain a target temperature"
) }
1133 opt_set_bool, &opt_autoengine,{ ("--auto-gpu"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autoengine) }, ("Automatically adjust all GPU engine clock speeds to maintain a target temperature"
) }
1134 "Automatically adjust all GPU engine clock speeds to maintain a target temperature"){ ("--auto-gpu"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_autoengine) }, ("Automatically adjust all GPU engine clock speeds to maintain a target temperature"
) }
,
1135#endif
1136 OPT_WITHOUT_ARG("--balance",{ ("--balance"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((set_balance))))))))), ((void
*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to even share balance"
) }
1137 set_balance, &pool_strategy,{ ("--balance"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((set_balance))))))))), ((void
*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to even share balance"
) }
1138 "Change multipool strategy from failover to even share balance"){ ("--balance"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((set_balance))))))))), ((void
*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to even share balance"
) }
,
1139 OPT_WITHOUT_ARG("--benchmark",{ ("--benchmark"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_benchmark) }, ("Run BFGMiner in benchmark mode - produces no shares"
) }
1140 opt_set_bool, &opt_benchmark,{ ("--benchmark"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_benchmark) }, ("Run BFGMiner in benchmark mode - produces no shares"
) }
1141 "Run BFGMiner in benchmark mode - produces no shares"){ ("--benchmark"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_benchmark) }, ("Run BFGMiner in benchmark mode - produces no shares"
) }
,
1142#if defined(USE_BITFORCE1)
1143 OPT_WITHOUT_ARG("--bfl-range",{ ("--bfl-range"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_bfl_noncerange) }, ("Use nonce range on bitforce devices if supported"
) }
1144 opt_set_bool, &opt_bfl_noncerange,{ ("--bfl-range"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_bfl_noncerange) }, ("Use nonce range on bitforce devices if supported"
) }
1145 "Use nonce range on bitforce devices if supported"){ ("--bfl-range"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_bfl_noncerange) }, ("Use nonce range on bitforce devices if supported"
) }
,
1146#endif
1147#ifdef WANT_CPUMINE1
1148 OPT_WITH_ARG("--bench-algo|-b",{ ("--bench-algo|-b"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_bench_algo) }, (opt_hidden) }
1149 set_int_0_to_9999, opt_show_intval, &opt_bench_algo,{ ("--bench-algo|-b"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_bench_algo) }, (opt_hidden) }
1150 opt_hidden){ ("--bench-algo|-b"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_bench_algo) }, (opt_hidden) }
,
1151#endif
1152#if BLKMAKER_VERSION(4L) > 1
1153 OPT_WITH_ARG("--coinbase-addr",{ ("--coinbase-addr"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_b58addr))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_script
) }, ("Set coinbase payout address for solo mining") }
1154 set_b58addr, NULL, &opt_coinbase_script,{ ("--coinbase-addr"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_b58addr))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_script
) }, ("Set coinbase payout address for solo mining") }
1155 "Set coinbase payout address for solo mining"){ ("--coinbase-addr"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_b58addr))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_script
) }, ("Set coinbase payout address for solo mining") }
,
1156 OPT_WITH_ARG("--coinbase-payout|--cbaddr|--cb-addr|--payout",{ ("--coinbase-payout|--cbaddr|--cb-addr|--payout"), OPT_HASARG
, ((void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_b58addr
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_script) }, (opt_hidden) }
1157 set_b58addr, NULL, &opt_coinbase_script,{ ("--coinbase-payout|--cbaddr|--cb-addr|--payout"), OPT_HASARG
, ((void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_b58addr
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_script) }, (opt_hidden) }
1158 opt_hidden){ ("--coinbase-payout|--cbaddr|--cb-addr|--payout"), OPT_HASARG
, ((void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_b58addr
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_script) }, (opt_hidden) }
,
1159#endif
1160#if BLKMAKER_VERSION(4L) > 0
1161 OPT_WITH_ARG("--coinbase-sig",{ ("--coinbase-sig"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_strdup))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_sig
) }, ("Set coinbase signature when possible") }
1162 set_strdup, NULL, &opt_coinbase_sig,{ ("--coinbase-sig"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_strdup))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_sig
) }, ("Set coinbase signature when possible") }
1163 "Set coinbase signature when possible"){ ("--coinbase-sig"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_strdup))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (&opt_coinbase_sig
) }, ("Set coinbase signature when possible") }
,
1164 OPT_WITH_ARG("--coinbase|--cbsig|--cb-sig|--cb|--prayer",{ ("--coinbase|--cbsig|--cb-sig|--cb|--prayer"), OPT_HASARG, (
(void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_strdup
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_sig) }, (opt_hidden) }
1165 set_strdup, NULL, &opt_coinbase_sig,{ ("--coinbase|--cbsig|--cb-sig|--cb|--prayer"), OPT_HASARG, (
(void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_strdup
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_sig) }, (opt_hidden) }
1166 opt_hidden){ ("--coinbase|--cbsig|--cb-sig|--cb|--prayer"), OPT_HASARG, (
(void*)0), ((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))((((set_strdup
))))))))), ((void (*)(char buf[], const void *))(((((void*)0)
)))), { (&opt_coinbase_sig) }, (opt_hidden) }
,
1167#endif
1168#ifdef HAVE_CURSES1
1169 OPT_WITHOUT_ARG("--compact",{ ("--compact"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_compact) }, ("Use compact display without per device statistics"
) }
1170 opt_set_bool, &opt_compact,{ ("--compact"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_compact) }, ("Use compact display without per device statistics"
) }
1171 "Use compact display without per device statistics"){ ("--compact"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_compact) }, ("Use compact display without per device statistics"
) }
,
1172#endif
1173#ifdef WANT_CPUMINE1
1174 OPT_WITH_ARG("--cpu-threads|-t",{ ("--cpu-threads|-t"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((force_nthreads_int))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_n_threads) }, ("Number of miner CPU threads") }
1175 force_nthreads_int, opt_show_intval, &opt_n_threads,{ ("--cpu-threads|-t"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((force_nthreads_int))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_n_threads) }, ("Number of miner CPU threads") }
1176 "Number of miner CPU threads"){ ("--cpu-threads|-t"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((force_nthreads_int))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_n_threads) }, ("Number of miner CPU threads") }
,
1177#endif
1178 OPT_WITHOUT_ARG("--debug|-D",{ ("--debug|-D"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((enable_debug))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug output"
) }
1179 enable_debug, &opt_debug,{ ("--debug|-D"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((enable_debug))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug output"
) }
1180 "Enable debug output"){ ("--debug|-D"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((enable_debug))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug output"
) }
,
1181 OPT_WITHOUT_ARG("--debuglog",{ ("--debuglog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug logging"
) }
1182 opt_set_bool, &opt_debug,{ ("--debuglog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug logging"
) }
1183 "Enable debug logging"){ ("--debuglog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_debug) }, ("Enable debug logging"
) }
,
1184 OPT_WITH_ARG("--device|-d",{ ("--device|-d"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_devices))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Select device to use, (Use repeat -d for multiple devices, default: all)"
) }
1185 set_devices, NULL, NULL,{ ("--device|-d"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_devices))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Select device to use, (Use repeat -d for multiple devices, default: all)"
) }
1186 "Select device to use, (Use repeat -d for multiple devices, default: all)"){ ("--device|-d"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_devices))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Select device to use, (Use repeat -d for multiple devices, default: all)"
) }
,
1187 OPT_WITHOUT_ARG("--disable-gpu|-G",{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1188 opt_set_bool, &opt_nogpu,{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1189#ifdef HAVE_OPENCL{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1190 "Disable GPU mining even if suitable devices exist"{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1191#else{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1192 opt_hidden{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1193#endif{ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
1194 ){ ("--disable-gpu|-G"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_nogpu) }, (ifdef 1 "Disable GPU mining even if suitable devices exist"
else opt_hidden endif) }
,
1195 OPT_WITHOUT_ARG("--disable-rejecting",{ ("--disable-rejecting"), OPT_NOARG, ((char *(*)(void *))(((
char *(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))
))), ((void*)0), ((void*)0), { (&opt_disable_pool) }, ("Automatically disable pools that continually reject shares"
) }
1196 opt_set_bool, &opt_disable_pool,{ ("--disable-rejecting"), OPT_NOARG, ((char *(*)(void *))(((
char *(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))
))), ((void*)0), ((void*)0), { (&opt_disable_pool) }, ("Automatically disable pools that continually reject shares"
) }
1197 "Automatically disable pools that continually reject shares"){ ("--disable-rejecting"), OPT_NOARG, ((char *(*)(void *))(((
char *(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))
))), ((void*)0), ((void*)0), { (&opt_disable_pool) }, ("Automatically disable pools that continually reject shares"
) }
,
1198#if defined(WANT_CPUMINE1) && (defined(HAVE_OPENCL1) || defined(USE_FPGA))
1199 OPT_WITHOUT_ARG("--enable-cpu|-C",{ ("--enable-cpu|-C"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_usecpu) }, ("Enable CPU mining with other mining (default: no CPU mining if other devices exist)"
) }
1200 opt_set_bool, &opt_usecpu,{ ("--enable-cpu|-C"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_usecpu) }, ("Enable CPU mining with other mining (default: no CPU mining if other devices exist)"
) }
1201 "Enable CPU mining with other mining (default: no CPU mining if other devices exist)"){ ("--enable-cpu|-C"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_usecpu) }, ("Enable CPU mining with other mining (default: no CPU mining if other devices exist)"
) }
,
1202#endif
1203 OPT_WITH_ARG("--expiry|-E",{ ("--expiry|-E"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (w/o longpoll active)"
) }
1204 set_int_0_to_9999, opt_show_intval, &opt_expiry,{ ("--expiry|-E"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (w/o longpoll active)"
) }
1205 "Upper bound on how many seconds after getting work we consider a share from it stale (w/o longpoll active)"){ ("--expiry|-E"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (w/o longpoll active)"
) }
,
1206 OPT_WITH_ARG("--expiry-lp",{ ("--expiry-lp"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry_lp
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (with longpoll active)"
) }
1207 set_int_0_to_9999, opt_show_intval, &opt_expiry_lp,{ ("--expiry-lp"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry_lp
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (with longpoll active)"
) }
1208 "Upper bound on how many seconds after getting work we consider a share from it stale (with longpoll active)"){ ("--expiry-lp"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_expiry_lp
) }, ("Upper bound on how many seconds after getting work we consider a share from it stale (with longpoll active)"
) }
,
1209 OPT_WITHOUT_ARG("--failover-only",{ ("--failover-only"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_fail_only) }, ("Don't leak work to backup pools when primary pool is lagging"
) }
1210 opt_set_bool, &opt_fail_only,{ ("--failover-only"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_fail_only) }, ("Don't leak work to backup pools when primary pool is lagging"
) }
1211 "Don't leak work to backup pools when primary pool is lagging"){ ("--failover-only"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_fail_only) }, ("Don't leak work to backup pools when primary pool is lagging"
) }
,
1212#ifdef USE_FPGA
1213 OPT_WITHOUT_ARG("--force-dev-init",{ ("--force-dev-init"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_force_dev_init) }, ("Always initialize devices when possible (such as bitstream uploads to some FPGAs)"
) }
1214 opt_set_bool, &opt_force_dev_init,{ ("--force-dev-init"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_force_dev_init) }, ("Always initialize devices when possible (such as bitstream uploads to some FPGAs)"
) }
1215 "Always initialize devices when possible (such as bitstream uploads to some FPGAs)"){ ("--force-dev-init"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_force_dev_init) }, ("Always initialize devices when possible (such as bitstream uploads to some FPGAs)"
) }
,
1216#endif
1217#ifdef HAVE_OPENCL1
1218 OPT_WITH_ARG("--gpu-dyninterval",{ ("--gpu-dyninterval"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_65535))))))))), (
(void (*)(char buf[], const void *))(((opt_show_intval)))), {
(&opt_dynamic_interval) }, ("Set the refresh interval in ms for GPUs using dynamic intensity"
) }
1219 set_int_1_to_65535, opt_show_intval, &opt_dynamic_interval,{ ("--gpu-dyninterval"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_65535))))))))), (
(void (*)(char buf[], const void *))(((opt_show_intval)))), {
(&opt_dynamic_interval) }, ("Set the refresh interval in ms for GPUs using dynamic intensity"
) }
1220 "Set the refresh interval in ms for GPUs using dynamic intensity"){ ("--gpu-dyninterval"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_65535))))))))), (
(void (*)(char buf[], const void *))(((opt_show_intval)))), {
(&opt_dynamic_interval) }, ("Set the refresh interval in ms for GPUs using dynamic intensity"
) }
,
1221 OPT_WITH_ARG("--gpu-platform",{ ("--gpu-platform"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_platform_id) }, ("Select OpenCL platform ID to use for GPU mining"
) }
1222 set_int_0_to_9999, opt_show_intval, &opt_platform_id,{ ("--gpu-platform"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_platform_id) }, ("Select OpenCL platform ID to use for GPU mining"
) }
1223 "Select OpenCL platform ID to use for GPU mining"){ ("--gpu-platform"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_platform_id) }, ("Select OpenCL platform ID to use for GPU mining"
) }
,
1224 OPT_WITH_ARG("--gpu-threads|-g",{ ("--gpu-threads|-g"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_1_to_10))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_g_threads) }, ("Number of threads per GPU (1 - 10)") }
1225 set_int_1_to_10, opt_show_intval, &opt_g_threads,{ ("--gpu-threads|-g"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_1_to_10))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_g_threads) }, ("Number of threads per GPU (1 - 10)") }
1226 "Number of threads per GPU (1 - 10)"){ ("--gpu-threads|-g"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_1_to_10))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_g_threads) }, ("Number of threads per GPU (1 - 10)") }
,
1227#ifdef HAVE_ADL1
1228 OPT_WITH_ARG("--gpu-engine",{ ("--gpu-engine"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_engine))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"
) }
1229 set_gpu_engine, NULL, NULL,{ ("--gpu-engine"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_engine))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"
) }
1230 "GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"){ ("--gpu-engine"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_engine))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("GPU engine (over)clock range in MHz - one value, range and/or comma separated list (e.g. 850-900,900,750-850)"
) }
,
1231 OPT_WITH_ARG("--gpu-fan",{ ("--gpu-fan"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_fan))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"
) }
1232 set_gpu_fan, NULL, NULL,{ ("--gpu-fan"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_fan))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"
) }
1233 "GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"){ ("--gpu-fan"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_fan))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU fan percentage range - one value, range and/or comma separated list (e.g. 0-85,85,65)"
) }
,
1234 OPT_WITH_ARG("--gpu-map",{ ("--gpu-map"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_map))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"
) }
1235 set_gpu_map, NULL, NULL,{ ("--gpu-map"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_map))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"
) }
1236 "Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"){ ("--gpu-map"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_map))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Map OpenCL to ADL device order manually, paired CSV (e.g. 1:0,2:1 maps OpenCL 1 to ADL 0, 2 to 1)"
) }
,
1237 OPT_WITH_ARG("--gpu-memclock",{ ("--gpu-memclock"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memclock))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card"
) }
1238 set_gpu_memclock, NULL, NULL,{ ("--gpu-memclock"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memclock))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card"
) }
1239 "Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card"){ ("--gpu-memclock"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memclock))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set the GPU memory (over)clock in MHz - one value for all or separate by commas for per card"
) }
,
1240 OPT_WITH_ARG("--gpu-memdiff",{ ("--gpu-memdiff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memdiff))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"
) }
1241 set_gpu_memdiff, NULL, NULL,{ ("--gpu-memdiff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memdiff))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"
) }
1242 "Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"){ ("--gpu-memdiff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_memdiff))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Set a fixed difference in clock speed between the GPU and memory in auto-gpu mode"
) }
,
1243 OPT_WITH_ARG("--gpu-powertune",{ ("--gpu-powertune"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_powertune))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Set the GPU powertune percentage - one value for all or separate by commas for per card"
) }
1244 set_gpu_powertune, NULL, NULL,{ ("--gpu-powertune"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_powertune))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Set the GPU powertune percentage - one value for all or separate by commas for per card"
) }
1245 "Set the GPU powertune percentage - one value for all or separate by commas for per card"){ ("--gpu-powertune"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_gpu_powertune))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Set the GPU powertune percentage - one value for all or separate by commas for per card"
) }
,
1246 OPT_WITHOUT_ARG("--gpu-reorder",{ ("--gpu-reorder"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_reorder) }, ("Attempt to reorder GPU devices according to PCI Bus ID"
) }
1247 opt_set_bool, &opt_reorder,{ ("--gpu-reorder"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_reorder) }, ("Attempt to reorder GPU devices according to PCI Bus ID"
) }
1248 "Attempt to reorder GPU devices according to PCI Bus ID"){ ("--gpu-reorder"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_reorder) }, ("Attempt to reorder GPU devices according to PCI Bus ID"
) }
,
1249 OPT_WITH_ARG("--gpu-vddc",{ ("--gpu-vddc"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_vddc))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Set the GPU voltage in Volts - one value for all or separate by commas for per card"
) }
1250 set_gpu_vddc, NULL, NULL,{ ("--gpu-vddc"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_vddc))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Set the GPU voltage in Volts - one value for all or separate by commas for per card"
) }
1251 "Set the GPU voltage in Volts - one value for all or separate by commas for per card"){ ("--gpu-vddc"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_gpu_vddc))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Set the GPU voltage in Volts - one value for all or separate by commas for per card"
) }
,
1252#endif
1253#ifdef USE_SCRYPT1
1254 OPT_WITH_ARG("--lookup-gap",{ ("--lookup-gap"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_lookup_gap))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Set GPU lookup gap for scrypt mining, comma separated")
}
1255 set_lookup_gap, NULL, NULL,{ ("--lookup-gap"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_lookup_gap))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Set GPU lookup gap for scrypt mining, comma separated")
}
1256 "Set GPU lookup gap for scrypt mining, comma separated"){ ("--lookup-gap"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_lookup_gap))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Set GPU lookup gap for scrypt mining, comma separated")
}
,
1257#endif
1258 OPT_WITH_ARG("--intensity|-I",{ ("--intensity|-I"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_intensity))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Intensity of GPU scanning (d or " "-10" " -> " "20" ", default: d to maintain desktop interactivity)"
) }
1259 set_intensity, NULL, NULL,{ ("--intensity|-I"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_intensity))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Intensity of GPU scanning (d or " "-10" " -> " "20" ", default: d to maintain desktop interactivity)"
) }
1260 "Intensity of GPU scanning (d or " _MIN_INTENSITY_STR " -> " _MAX_INTENSITY_STR ", default: d to maintain desktop interactivity)"){ ("--intensity|-I"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_intensity))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Intensity of GPU scanning (d or " "-10" " -> " "20" ", default: d to maintain desktop interactivity)"
) }
,
1261#endif
1262#if defined(HAVE_OPENCL1) || defined(USE_MODMINER1) || defined(USE_X65001) || defined(USE_ZTEX1)
1263 OPT_WITH_ARG("--kernel-path|-K",{ ("--kernel-path|-K"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((opt_show_charp)))), { (&opt_kernel_path
) }, ("Specify a path to where bitstream and kernel files are"
) }
1264 opt_set_charp, opt_show_charp, &opt_kernel_path,{ ("--kernel-path|-K"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((opt_show_charp)))), { (&opt_kernel_path
) }, ("Specify a path to where bitstream and kernel files are"
) }
1265 "Specify a path to where bitstream and kernel files are"){ ("--kernel-path|-K"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((opt_show_charp)))), { (&opt_kernel_path
) }, ("Specify a path to where bitstream and kernel files are"
) }
,
1266#endif
1267#ifdef HAVE_OPENCL1
1268 OPT_WITH_ARG("--kernel|-k",{ ("--kernel|-k"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_kernel))))))))), ((void (*)(char buf[
], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"
) }
1269 set_kernel, NULL, NULL,{ ("--kernel|-k"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_kernel))))))))), ((void (*)(char buf[
], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"
) }
1270 "Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"){ ("--kernel|-k"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_kernel))))))))), ((void (*)(char buf[
], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"
) }
,
1271#endif
1272#ifdef USE_ICARUS1
1273 OPT_WITH_ARG("--icarus-options",{ ("--icarus-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1274 set_icarus_options, NULL, NULL,{ ("--icarus-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1275 opt_hidden){ ("--icarus-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
,
1276 OPT_WITH_ARG("--icarus-timing",{ ("--icarus-timing"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_timing))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1277 set_icarus_timing, NULL, NULL,{ ("--icarus-timing"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_timing))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1278 opt_hidden){ ("--icarus-timing"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_icarus_timing))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
,
1279#endif
1280#ifdef USE_AVALON1
1281 OPT_WITH_ARG("--avalon-options",{ ("--avalon-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_avalon_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1282 set_avalon_options, NULL, NULL,{ ("--avalon-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_avalon_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
1283 opt_hidden){ ("--avalon-options"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_avalon_options))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, (opt_hidden) }
,
1284#endif
1285 OPT_WITHOUT_ARG("--load-balance",{ ("--load-balance"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_loadbalance)))))))))
, ((void*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to efficiency based balance"
) }
1286 set_loadbalance, &pool_strategy,{ ("--load-balance"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_loadbalance)))))))))
, ((void*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to efficiency based balance"
) }
1287 "Change multipool strategy from failover to efficiency based balance"){ ("--load-balance"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_loadbalance)))))))))
, ((void*)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to efficiency based balance"
) }
,
1288 OPT_WITH_ARG("--log|-l",{ ("--log|-l"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_log_interval
) }, ("Interval in seconds between log output") }
1289 set_int_0_to_9999, opt_show_intval, &opt_log_interval,{ ("--log|-l"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_log_interval
) }, ("Interval in seconds between log output") }
1290 "Interval in seconds between log output"){ ("--log|-l"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_log_interval
) }, ("Interval in seconds between log output") }
,
1291#if defined(unix1)
1292 OPT_WITH_ARG("--monitor|-m",{ ("--monitor|-m"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_stderr_cmd
) }, ("Use custom pipe cmd for output messages") }
1293 opt_set_charp, NULL, &opt_stderr_cmd,{ ("--monitor|-m"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_stderr_cmd
) }, ("Use custom pipe cmd for output messages") }
1294 "Use custom pipe cmd for output messages"){ ("--monitor|-m"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_stderr_cmd
) }, ("Use custom pipe cmd for output messages") }
,
1295#endif // defined(unix)
1296 OPT_WITHOUT_ARG("--net-delay",{ ("--net-delay"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_delaynet) }, ("Impose small delays in networking to not overload slow routers"
) }
1297 opt_set_bool, &opt_delaynet,{ ("--net-delay"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_delaynet) }, ("Impose small delays in networking to not overload slow routers"
) }
1298 "Impose small delays in networking to not overload slow routers"){ ("--net-delay"), OPT_NOARG, ((char *(*)(void *))(((char *(*
)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_delaynet) }, ("Impose small delays in networking to not overload slow routers"
) }
,
1299 OPT_WITHOUT_ARG("--no-adl",{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1300 opt_set_bool, &opt_noadl,{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1301#ifdef HAVE_ADL{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1302 "Disable the ATI display library used for monitoring and setting GPU parameters"{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1303#else{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1304 opt_hidden{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1305#endif{ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
1306 ){ ("--no-adl"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_noadl) }, (ifdef 1 "Disable the ATI display library used for monitoring and setting GPU parameters"
else opt_hidden endif) }
,
1307 OPT_WITHOUT_ARG("--no-gbt",{ ("--no-gbt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_invbool))))))))), ((void
*)0), ((void*)0), { (&want_gbt) }, ("Disable getblocktemplate support"
) }
1308 opt_set_invbool, &want_gbt,{ ("--no-gbt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_invbool))))))))), ((void
*)0), ((void*)0), { (&want_gbt) }, ("Disable getblocktemplate support"
) }
1309 "Disable getblocktemplate support"){ ("--no-gbt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_invbool))))))))), ((void
*)0), ((void*)0), { (&want_gbt) }, ("Disable getblocktemplate support"
) }
,
1310 OPT_WITHOUT_ARG("--no-getwork",{ ("--no-getwork"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_getwork) }, ("Disable getwork support"
) }
1311 opt_set_invbool, &want_getwork,{ ("--no-getwork"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_getwork) }, ("Disable getwork support"
) }
1312 "Disable getwork support"){ ("--no-getwork"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_getwork) }, ("Disable getwork support"
) }
,
1313 OPT_WITHOUT_ARG("--no-longpoll",{ ("--no-longpoll"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&want_longpoll) }, ("Disable X-Long-Polling support"
) }
1314 opt_set_invbool, &want_longpoll,{ ("--no-longpoll"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&want_longpoll) }, ("Disable X-Long-Polling support"
) }
1315 "Disable X-Long-Polling support"){ ("--no-longpoll"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&want_longpoll) }, ("Disable X-Long-Polling support"
) }
,
1316 OPT_WITHOUT_ARG("--no-pool-disable",{ ("--no-pool-disable"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_disable_pool) }, (opt_hidden
) }
1317 opt_set_invbool, &opt_disable_pool,{ ("--no-pool-disable"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_disable_pool) }, (opt_hidden
) }
1318 opt_hidden){ ("--no-pool-disable"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_disable_pool) }, (opt_hidden
) }
,
1319 OPT_WITHOUT_ARG("--no-restart",{ ("--no-restart"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&opt_restart) }, ("Do not attempt to restart devices that hang"
) }
1320 opt_set_invbool, &opt_restart,{ ("--no-restart"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&opt_restart) }, ("Do not attempt to restart devices that hang"
) }
1321 "Do not attempt to restart devices that hang"{ ("--no-restart"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&opt_restart) }, ("Do not attempt to restart devices that hang"
) }
1322 ){ ("--no-restart"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&opt_restart) }, ("Do not attempt to restart devices that hang"
) }
,
1323 OPT_WITHOUT_ARG("--no-show-processors",{ ("--no-show-processors"), OPT_NOARG, ((char *(*)(void *))((
(char *(*)(void *))(((char *(*)(void *))((((opt_set_invbool))
))))))), ((void*)0), ((void*)0), { (&opt_show_procs) }, (
opt_hidden) }
1324 opt_set_invbool, &opt_show_procs,{ ("--no-show-processors"), OPT_NOARG, ((char *(*)(void *))((
(char *(*)(void *))(((char *(*)(void *))((((opt_set_invbool))
))))))), ((void*)0), ((void*)0), { (&opt_show_procs) }, (
opt_hidden) }
1325 opt_hidden){ ("--no-show-processors"), OPT_NOARG, ((char *(*)(void *))((
(char *(*)(void *))(((char *(*)(void *))((((opt_set_invbool))
))))))), ((void*)0), ((void*)0), { (&opt_show_procs) }, (
opt_hidden) }
,
1326 OPT_WITHOUT_ARG("--no-show-procs",{ ("--no-show-procs"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden
) }
1327 opt_set_invbool, &opt_show_procs,{ ("--no-show-procs"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden
) }
1328 opt_hidden){ ("--no-show-procs"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden
) }
,
1329 OPT_WITHOUT_ARG("--no-stratum",{ ("--no-stratum"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_stratum) }, ("Disable Stratum detection"
) }
1330 opt_set_invbool, &want_stratum,{ ("--no-stratum"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_stratum) }, ("Disable Stratum detection"
) }
1331 "Disable Stratum detection"){ ("--no-stratum"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_invbool))))))))),
((void*)0), ((void*)0), { (&want_stratum) }, ("Disable Stratum detection"
) }
,
1332 OPT_WITHOUT_ARG("--no-submit-stale",{ ("--no-submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_submit_stale) }, ("Don't submit shares if they are detected as stale"
) }
1333 opt_set_invbool, &opt_submit_stale,{ ("--no-submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_submit_stale) }, ("Don't submit shares if they are detected as stale"
) }
1334 "Don't submit shares if they are detected as stale"){ ("--no-submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))
)), ((void*)0), ((void*)0), { (&opt_submit_stale) }, ("Don't submit shares if they are detected as stale"
) }
,
1335 OPT_WITH_ARG("--pass|-p",{ ("--pass|-p"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_pass))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Password for bitcoin JSON-RPC server"
) }
1336 set_pass, NULL, NULL,{ ("--pass|-p"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_pass))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Password for bitcoin JSON-RPC server"
) }
1337 "Password for bitcoin JSON-RPC server"){ ("--pass|-p"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_pass))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Password for bitcoin JSON-RPC server"
) }
,
1338 OPT_WITHOUT_ARG("--per-device-stats",{ ("--per-device-stats"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&want_per_device_stats) }, ("Force verbose mode and output per-device statistics"
) }
1339 opt_set_bool, &want_per_device_stats,{ ("--per-device-stats"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&want_per_device_stats) }, ("Force verbose mode and output per-device statistics"
) }
1340 "Force verbose mode and output per-device statistics"){ ("--per-device-stats"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&want_per_device_stats) }, ("Force verbose mode and output per-device statistics"
) }
,
1341 OPT_WITH_ARG("--pool-priority",{ ("--pool-priority"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_priority))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Priority for just the previous-defined pool") }
1342 set_pool_priority, NULL, NULL,{ ("--pool-priority"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_priority))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Priority for just the previous-defined pool") }
1343 "Priority for just the previous-defined pool"){ ("--pool-priority"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_priority))))))))), ((void
(*)(char buf[], const void *))(((((void*)0))))), { (((void*)
0)) }, ("Priority for just the previous-defined pool") }
,
1344 OPT_WITH_ARG("--pool-proxy|-x",{ ("--pool-proxy|-x"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_proxy))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Proxy URI to use for connecting to just the previous-defined pool"
) }
1345 set_pool_proxy, NULL, NULL,{ ("--pool-proxy|-x"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_proxy))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Proxy URI to use for connecting to just the previous-defined pool"
) }
1346 "Proxy URI to use for connecting to just the previous-defined pool"){ ("--pool-proxy|-x"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_pool_proxy))))))))), ((void (*
)(char buf[], const void *))(((((void*)0))))), { (((void*)0))
}, ("Proxy URI to use for connecting to just the previous-defined pool"
) }
,
1347 OPT_WITH_ARG("--force-rollntime", // NOTE: must be after --pass for config file ordering{ ("--force-rollntime"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_pool_force_rollntime))))))
))), ((void (*)(char buf[], const void *))(((((void*)0))))), {
(((void*)0)) }, (opt_hidden) }
1348 set_pool_force_rollntime, NULL, NULL,{ ("--force-rollntime"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_pool_force_rollntime))))))
))), ((void (*)(char buf[], const void *))(((((void*)0))))), {
(((void*)0)) }, (opt_hidden) }
1349 opt_hidden){ ("--force-rollntime"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_pool_force_rollntime))))))
))), ((void (*)(char buf[], const void *))(((((void*)0))))), {
(((void*)0)) }, (opt_hidden) }
,
1350 OPT_WITHOUT_ARG("--protocol-dump|-P",{ ("--protocol-dump|-P"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_protocol) }, ("Verbose dump of protocol-level activities"
) }
1351 opt_set_bool, &opt_protocol,{ ("--protocol-dump|-P"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_protocol) }, ("Verbose dump of protocol-level activities"
) }
1352 "Verbose dump of protocol-level activities"){ ("--protocol-dump|-P"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_protocol) }, ("Verbose dump of protocol-level activities"
) }
,
1353 OPT_WITH_ARG("--queue|-Q",{ ("--queue|-Q"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_queue
) }, ("Minimum number of work items to have queued (0+)") }
1354 set_int_0_to_9999, opt_show_intval, &opt_queue,{ ("--queue|-Q"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_queue
) }, ("Minimum number of work items to have queued (0+)") }
1355 "Minimum number of work items to have queued (0+)"){ ("--queue|-Q"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_queue
) }, ("Minimum number of work items to have queued (0+)") }
,
1356 OPT_WITHOUT_ARG("--quiet|-q",{ ("--quiet|-q"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_quiet) }, ("Disable logging output, display status and errors"
) }
1357 opt_set_bool, &opt_quiet,{ ("--quiet|-q"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_quiet) }, ("Disable logging output, display status and errors"
) }
1358 "Disable logging output, display status and errors"){ ("--quiet|-q"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_quiet) }, ("Disable logging output, display status and errors"
) }
,
1359 OPT_WITHOUT_ARG("--quiet-work-updates|--quiet-work-update",{ ("--quiet-work-updates|--quiet-work-update"), OPT_NOARG, ((
char *(*)(void *))(((char *(*)(void *))(((char *(*)(void *))(
(((opt_set_bool))))))))), ((void*)0), ((void*)0), { (&opt_quiet_work_updates
) }, (opt_hidden) }
1360 opt_set_bool, &opt_quiet_work_updates,{ ("--quiet-work-updates|--quiet-work-update"), OPT_NOARG, ((
char *(*)(void *))(((char *(*)(void *))(((char *(*)(void *))(
(((opt_set_bool))))))))), ((void*)0), ((void*)0), { (&opt_quiet_work_updates
) }, (opt_hidden) }
1361 opt_hidden){ ("--quiet-work-updates|--quiet-work-update"), OPT_NOARG, ((
char *(*)(void *))(((char *(*)(void *))(((char *(*)(void *))(
(((opt_set_bool))))))))), ((void*)0), ((void*)0), { (&opt_quiet_work_updates
) }, (opt_hidden) }
,
1362 OPT_WITHOUT_ARG("--real-quiet",{ ("--real-quiet"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_realquiet) }, ("Disable all output"
) }
1363 opt_set_bool, &opt_realquiet,{ ("--real-quiet"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_realquiet) }, ("Disable all output"
) }
1364 "Disable all output"){ ("--real-quiet"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_realquiet) }, ("Disable all output"
) }
,
1365 OPT_WITHOUT_ARG("--remove-disabled",{ ("--remove-disabled"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_removedisabled) }, ("Remove disabled devices entirely, as if they didn't exist"
) }
1366 opt_set_bool, &opt_removedisabled,{ ("--remove-disabled"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_removedisabled) }, ("Remove disabled devices entirely, as if they didn't exist"
) }
1367 "Remove disabled devices entirely, as if they didn't exist"){ ("--remove-disabled"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_removedisabled) }, ("Remove disabled devices entirely, as if they didn't exist"
) }
,
1368 OPT_WITH_ARG("--request-diff",{ ("--request-diff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_request_diff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_floatval)))), { (&
request_pdiff) }, ("Request a specific difficulty from pools"
) }
1369 set_request_diff, opt_show_floatval, &request_pdiff,{ ("--request-diff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_request_diff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_floatval)))), { (&
request_pdiff) }, ("Request a specific difficulty from pools"
) }
1370 "Request a specific difficulty from pools"){ ("--request-diff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_request_diff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_floatval)))), { (&
request_pdiff) }, ("Request a specific difficulty from pools"
) }
,
1371 OPT_WITH_ARG("--retries",{ ("--retries"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((opt_show_intval)))), { (&opt_retries
) }, ("Number of times to retry failed submissions before giving up (-1 means never)"
) }
1372 opt_set_intval, opt_show_intval, &opt_retries,{ ("--retries"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((opt_show_intval)))), { (&opt_retries
) }, ("Number of times to retry failed submissions before giving up (-1 means never)"
) }
1373 "Number of times to retry failed submissions before giving up (-1 means never)"){ ("--retries"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((opt_show_intval)))), { (&opt_retries
) }, ("Number of times to retry failed submissions before giving up (-1 means never)"
) }
,
1374 OPT_WITH_ARG("--retry-pause",{ ("--retry-pause"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_null))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, (opt_hidden
) }
1375 set_null, NULL, NULL,{ ("--retry-pause"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_null))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, (opt_hidden
) }
1376 opt_hidden){ ("--retry-pause"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_null))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, (opt_hidden
) }
,
1377 OPT_WITH_ARG("--rotate",{ ("--rotate"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_rotate))))))))), ((void (*)(char buf[
], const void *))(((opt_show_intval)))), { (&opt_rotate_period
) }, ("Change multipool strategy from failover to regularly rotate at N minutes"
) }
1378 set_rotate, opt_show_intval, &opt_rotate_period,{ ("--rotate"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_rotate))))))))), ((void (*)(char buf[
], const void *))(((opt_show_intval)))), { (&opt_rotate_period
) }, ("Change multipool strategy from failover to regularly rotate at N minutes"
) }
1379 "Change multipool strategy from failover to regularly rotate at N minutes"){ ("--rotate"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_rotate))))))))), ((void (*)(char buf[
], const void *))(((opt_show_intval)))), { (&opt_rotate_period
) }, ("Change multipool strategy from failover to regularly rotate at N minutes"
) }
,
1380 OPT_WITHOUT_ARG("--round-robin",{ ("--round-robin"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_rr))))))))), ((void*
)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to round robin on failure"
) }
1381 set_rr, &pool_strategy,{ ("--round-robin"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_rr))))))))), ((void*
)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to round robin on failure"
) }
1382 "Change multipool strategy from failover to round robin on failure"){ ("--round-robin"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((set_rr))))))))), ((void*
)0), ((void*)0), { (&pool_strategy) }, ("Change multipool strategy from failover to round robin on failure"
) }
,
1383#ifdef USE_FPGA_SERIAL
1384 OPT_WITH_ARG("--scan-serial|-S",{ ("--scan-serial|-S"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((add_serial))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Serial port to probe for FPGA Mining device"
) }
1385 add_serial, NULL, NULL,{ ("--scan-serial|-S"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((add_serial))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Serial port to probe for FPGA Mining device"
) }
1386 "Serial port to probe for FPGA Mining device"){ ("--scan-serial|-S"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((add_serial))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Serial port to probe for FPGA Mining device"
) }
,
1387#endif
1388 OPT_WITH_ARG("--scan-time|-s",{ ("--scan-time|-s"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_scantime) }, ("Upper bound on time spent scanning current work, in seconds"
) }
1389 set_int_0_to_9999, opt_show_intval, &opt_scantime,{ ("--scan-time|-s"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_scantime) }, ("Upper bound on time spent scanning current work, in seconds"
) }
1390 "Upper bound on time spent scanning current work, in seconds"){ ("--scan-time|-s"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_int_0_to_9999))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_scantime) }, ("Upper bound on time spent scanning current work, in seconds"
) }
,
1391 OPT_WITH_ARG("--scantime",{ ("--scantime"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_scantime
) }, (opt_hidden) }
1392 set_int_0_to_9999, opt_show_intval, &opt_scantime,{ ("--scantime"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_scantime
) }, (opt_hidden) }
1393 opt_hidden){ ("--scantime"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_int_0_to_9999))))))))), ((void (*)(char
buf[], const void *))(((opt_show_intval)))), { (&opt_scantime
) }, (opt_hidden) }
,
1394 OPT_WITH_ARG("--sched-start",{ ("--sched-start"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstart
) }, ("Set a time of day in HH:MM to start mining (a once off without a stop time)"
) }
1395 set_schedtime, NULL, &schedstart,{ ("--sched-start"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstart
) }, ("Set a time of day in HH:MM to start mining (a once off without a stop time)"
) }
1396 "Set a time of day in HH:MM to start mining (a once off without a stop time)"){ ("--sched-start"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstart
) }, ("Set a time of day in HH:MM to start mining (a once off without a stop time)"
) }
,
1397 OPT_WITH_ARG("--sched-stop",{ ("--sched-stop"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstop
) }, ("Set a time of day in HH:MM to stop mining (will quit without a start time)"
) }
1398 set_schedtime, NULL, &schedstop,{ ("--sched-stop"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstop
) }, ("Set a time of day in HH:MM to stop mining (will quit without a start time)"
) }
1399 "Set a time of day in HH:MM to stop mining (will quit without a start time)"){ ("--sched-stop"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_schedtime))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&schedstop
) }, ("Set a time of day in HH:MM to stop mining (will quit without a start time)"
) }
,
1400#ifdef USE_SCRYPT1
1401 OPT_WITHOUT_ARG("--scrypt",{ ("--scrypt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_scrypt) }, ("Use the scrypt algorithm for mining (non-bitcoin)"
) }
1402 opt_set_bool, &opt_scrypt,{ ("--scrypt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_scrypt) }, ("Use the scrypt algorithm for mining (non-bitcoin)"
) }
1403 "Use the scrypt algorithm for mining (non-bitcoin)"){ ("--scrypt"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&opt_scrypt) }, ("Use the scrypt algorithm for mining (non-bitcoin)"
) }
,
1404#ifdef HAVE_OPENCL1
1405 OPT_WITH_ARG("--shaders",{ ("--shaders"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_shaders))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU shaders per card for tuning scrypt, comma separated"
) }
1406 set_shaders, NULL, NULL,{ ("--shaders"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_shaders))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU shaders per card for tuning scrypt, comma separated"
) }
1407 "GPU shaders per card for tuning scrypt, comma separated"){ ("--shaders"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_shaders))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("GPU shaders per card for tuning scrypt, comma separated"
) }
,
1408#endif
1409#endif
1410 OPT_WITH_ARG("--sharelog",{ ("--sharelog"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_sharelog))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Append share log to file"
) }
1411 set_sharelog, NULL, NULL,{ ("--sharelog"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_sharelog))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Append share log to file"
) }
1412 "Append share log to file"){ ("--sharelog"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_sharelog))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Append share log to file"
) }
,
1413 OPT_WITH_ARG("--shares",{ ("--shares"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (&opt_shares) }, (
"Quit after mining N shares (default: unlimited)") }
1414 opt_set_intval, NULL, &opt_shares,{ ("--shares"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (&opt_shares) }, (
"Quit after mining N shares (default: unlimited)") }
1415 "Quit after mining N shares (default: unlimited)"){ ("--shares"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_intval))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (&opt_shares) }, (
"Quit after mining N shares (default: unlimited)") }
,
1416 OPT_WITHOUT_ARG("--show-processors",{ ("--show-processors"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_show_procs) }, ("Show per processor statistics in summary"
) }
1417 opt_set_bool, &opt_show_procs,{ ("--show-processors"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_show_procs) }, ("Show per processor statistics in summary"
) }
1418 "Show per processor statistics in summary"){ ("--show-processors"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))),
((void*)0), ((void*)0), { (&opt_show_procs) }, ("Show per processor statistics in summary"
) }
,
1419 OPT_WITHOUT_ARG("--show-procs",{ ("--show-procs"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden)
}
1420 opt_set_bool, &opt_show_procs,{ ("--show-procs"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden)
}
1421 opt_hidden){ ("--show-procs"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((
void*)0), ((void*)0), { (&opt_show_procs) }, (opt_hidden)
}
,
1422 OPT_WITH_ARG("--skip-security-checks",{ ("--skip-security-checks"), OPT_HASARG, ((void*)0), ((char *
(*)(const char *,void *))(((char *(*)(const char *,void *))((
(char *(*)(const char *,void *))((((set_int_0_to_9999))))))))
), ((void (*)(char buf[], const void *))(((((void*)0))))), { (
&opt_skip_checks) }, ("Skip security checks sometimes to save bandwidth; only check 1/<arg>th of the time (default: never skip)"
) }
1423 set_int_0_to_9999, NULL, &opt_skip_checks,{ ("--skip-security-checks"), OPT_HASARG, ((void*)0), ((char *
(*)(const char *,void *))(((char *(*)(const char *,void *))((
(char *(*)(const char *,void *))((((set_int_0_to_9999))))))))
), ((void (*)(char buf[], const void *))(((((void*)0))))), { (
&opt_skip_checks) }, ("Skip security checks sometimes to save bandwidth; only check 1/<arg>th of the time (default: never skip)"
) }
1424 "Skip security checks sometimes to save bandwidth; only check 1/<arg>th of the time (default: never skip)"){ ("--skip-security-checks"), OPT_HASARG, ((void*)0), ((char *
(*)(const char *,void *))(((char *(*)(const char *,void *))((
(char *(*)(const char *,void *))((((set_int_0_to_9999))))))))
), ((void (*)(char buf[], const void *))(((((void*)0))))), { (
&opt_skip_checks) }, ("Skip security checks sometimes to save bandwidth; only check 1/<arg>th of the time (default: never skip)"
) }
,
1425 OPT_WITH_ARG("--socks-proxy",{ ("--socks-proxy"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_socks_proxy
) }, ("Set socks4 proxy (host:port)") }
1426 opt_set_charp, NULL, &opt_socks_proxy,{ ("--socks-proxy"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_socks_proxy
) }, ("Set socks4 proxy (host:port)") }
1427 "Set socks4 proxy (host:port)"){ ("--socks-proxy"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((opt_set_charp))))))))), ((void (*)
(char buf[], const void *))(((((void*)0))))), { (&opt_socks_proxy
) }, ("Set socks4 proxy (host:port)") }
,
1428 OPT_WITHOUT_ARG("--submit-stale",{ ("--submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_submit_stale) }, (opt_hidden
) }
1429 opt_set_bool, &opt_submit_stale,{ ("--submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_submit_stale) }, (opt_hidden
) }
1430 opt_hidden){ ("--submit-stale"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_bool))))))))), (
(void*)0), ((void*)0), { (&opt_submit_stale) }, (opt_hidden
) }
,
1431 OPT_WITHOUT_ARG("--submit-threads",{ ("--submit-threads"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_intval))))))))
), ((void*)0), ((void*)0), { (&opt_submit_threads) }, ("Minimum number of concurrent share submissions (default: 64)"
) }
1432 opt_set_intval, &opt_submit_threads,{ ("--submit-threads"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_intval))))))))
), ((void*)0), ((void*)0), { (&opt_submit_threads) }, ("Minimum number of concurrent share submissions (default: 64)"
) }
1433 "Minimum number of concurrent share submissions (default: 64)"){ ("--submit-threads"), OPT_NOARG, ((char *(*)(void *))(((char
*(*)(void *))(((char *(*)(void *))((((opt_set_intval))))))))
), ((void*)0), ((void*)0), { (&opt_submit_threads) }, ("Minimum number of concurrent share submissions (default: 64)"
) }
,
1434#ifdef HAVE_SYSLOG_H1
1435 OPT_WITHOUT_ARG("--syslog",{ ("--syslog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&use_syslog) }, ("Use system log for output messages (default: standard error)"
) }
1436 opt_set_bool, &use_syslog,{ ("--syslog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&use_syslog) }, ("Use system log for output messages (default: standard error)"
) }
1437 "Use system log for output messages (default: standard error)"){ ("--syslog"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(void
*))(((char *(*)(void *))((((opt_set_bool))))))))), ((void*)0
), ((void*)0), { (&use_syslog) }, ("Use system log for output messages (default: standard error)"
) }
,
1438#endif
1439#if defined(HAVE_ADL1) || defined(USE_BITFORCE1) || defined(USE_MODMINER1)
1440 OPT_WITH_ARG("--temp-cutoff",{ ("--temp-cutoff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_cutoff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_cutofftemp) }, ("Temperature where a device will be automatically disabled, one value or comma separated list"
) }
1441 set_temp_cutoff, opt_show_intval, &opt_cutofftemp,{ ("--temp-cutoff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_cutoff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_cutofftemp) }, ("Temperature where a device will be automatically disabled, one value or comma separated list"
) }
1442 "Temperature where a device will be automatically disabled, one value or comma separated list"){ ("--temp-cutoff"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_cutoff))))))))), ((void (
*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_cutofftemp) }, ("Temperature where a device will be automatically disabled, one value or comma separated list"
) }
,
1443#endif
1444#if defined(HAVE_ADL1) || defined(USE_MODMINER1)
1445 OPT_WITH_ARG("--temp-hysteresis",{ ("--temp-hysteresis"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_10))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_hysteresis) }, ("Set how much the temperature can fluctuate outside limits when automanaging speeds"
) }
1446 set_int_1_to_10, opt_show_intval, &opt_hysteresis,{ ("--temp-hysteresis"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_10))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_hysteresis) }, ("Set how much the temperature can fluctuate outside limits when automanaging speeds"
) }
1447 "Set how much the temperature can fluctuate outside limits when automanaging speeds"){ ("--temp-hysteresis"), OPT_HASARG, ((void*)0), ((char *(*)(
const char *,void *))(((char *(*)(const char *,void *))(((char
*(*)(const char *,void *))((((set_int_1_to_10))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_hysteresis) }, ("Set how much the temperature can fluctuate outside limits when automanaging speeds"
) }
,
1448#ifdef HAVE_ADL1
1449 OPT_WITH_ARG("--temp-overheat",{ ("--temp-overheat"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_overheat))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_overheattemp) }, ("Overheat temperature when automatically managing fan and GPU speeds, one value or comma separated list"
) }
1450 set_temp_overheat, opt_show_intval, &opt_overheattemp,{ ("--temp-overheat"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_overheat))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_overheattemp) }, ("Overheat temperature when automatically managing fan and GPU speeds, one value or comma separated list"
) }
1451 "Overheat temperature when automatically managing fan and GPU speeds, one value or comma separated list"){ ("--temp-overheat"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_overheat))))))))), ((void
(*)(char buf[], const void *))(((opt_show_intval)))), { (&
opt_overheattemp) }, ("Overheat temperature when automatically managing fan and GPU speeds, one value or comma separated list"
) }
,
1452#endif
1453 OPT_WITH_ARG("--temp-target",{ ("--temp-target"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_target))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Target temperature when automatically managing fan and clock speeds, one value or comma separated list"
) }
1454 set_temp_target, NULL, NULL,{ ("--temp-target"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_target))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Target temperature when automatically managing fan and clock speeds, one value or comma separated list"
) }
1455 "Target temperature when automatically managing fan and clock speeds, one value or comma separated list"){ ("--temp-target"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_temp_target))))))))), ((void (
*)(char buf[], const void *))(((((void*)0))))), { (((void*)0)
) }, ("Target temperature when automatically managing fan and clock speeds, one value or comma separated list"
) }
,
1456#endif
1457 OPT_WITHOUT_ARG("--text-only|-T",{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1458 opt_set_invbool, &use_curses,{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1459#ifdef HAVE_CURSES{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1460 "Disable ncurses formatted screen output"{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1461#else{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1462 opt_hidden{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1463#endif{ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
1464 ){ ("--text-only|-T"), OPT_NOARG, ((char *(*)(void *))(((char *
(*)(void *))(((char *(*)(void *))((((opt_set_invbool)))))))))
, ((void*)0), ((void*)0), { (&use_curses) }, (ifdef 1 "Disable ncurses formatted screen output"
else opt_hidden endif) }
,
1465#if defined(USE_SCRYPT1) && defined(HAVE_OPENCL1)
1466 OPT_WITH_ARG("--thread-concurrency",{ ("--thread-concurrency"), OPT_HASARG, ((void*)0), ((char *(
*)(const char *,void *))(((char *(*)(const char *,void *))(((
char *(*)(const char *,void *))((((set_thread_concurrency))))
))))), ((void (*)(char buf[], const void *))(((((void*)0)))))
, { (((void*)0)) }, ("Set GPU thread concurrency for scrypt mining, comma separated"
) }
1467 set_thread_concurrency, NULL, NULL,{ ("--thread-concurrency"), OPT_HASARG, ((void*)0), ((char *(
*)(const char *,void *))(((char *(*)(const char *,void *))(((
char *(*)(const char *,void *))((((set_thread_concurrency))))
))))), ((void (*)(char buf[], const void *))(((((void*)0)))))
, { (((void*)0)) }, ("Set GPU thread concurrency for scrypt mining, comma separated"
) }
1468 "Set GPU thread concurrency for scrypt mining, comma separated"){ ("--thread-concurrency"), OPT_HASARG, ((void*)0), ((char *(
*)(const char *,void *))(((char *(*)(const char *,void *))(((
char *(*)(const char *,void *))((((set_thread_concurrency))))
))))), ((void (*)(char buf[], const void *))(((((void*)0)))))
, { (((void*)0)) }, ("Set GPU thread concurrency for scrypt mining, comma separated"
) }
,
1469#endif
1470 OPT_WITH_ARG("--url|-o",{ ("--url|-o"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_url))))))))), ((void (*)(char buf[], const
void *))(((((void*)0))))), { (((void*)0)) }, ("URL for bitcoin JSON-RPC server"
) }
1471 set_url, NULL, NULL,{ ("--url|-o"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_url))))))))), ((void (*)(char buf[], const
void *))(((((void*)0))))), { (((void*)0)) }, ("URL for bitcoin JSON-RPC server"
) }
1472 "URL for bitcoin JSON-RPC server"){ ("--url|-o"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_url))))))))), ((void (*)(char buf[], const
void *))(((((void*)0))))), { (((void*)0)) }, ("URL for bitcoin JSON-RPC server"
) }
,
1473 OPT_WITH_ARG("--user|-u",{ ("--user|-u"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_user))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Username for bitcoin JSON-RPC server"
) }
1474 set_user, NULL, NULL,{ ("--user|-u"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_user))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Username for bitcoin JSON-RPC server"
) }
1475 "Username for bitcoin JSON-RPC server"){ ("--user|-u"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((set_user))))))))), ((void (*)(char buf[],
const void *))(((((void*)0))))), { (((void*)0)) }, ("Username for bitcoin JSON-RPC server"
) }
,
1476#ifdef HAVE_OPENCL1
1477 OPT_WITH_ARG("--vectors|-v",{ ("--vectors|-v"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_vector))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override detected optimal vector (1, 2 or 4) - one value or comma separated list"
) }
1478 set_vector, NULL, NULL,{ ("--vectors|-v"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_vector))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override detected optimal vector (1, 2 or 4) - one value or comma separated list"
) }
1479 "Override detected optimal vector (1, 2 or 4) - one value or comma separated list"){ ("--vectors|-v"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_vector))))))))), ((void (*)(char
buf[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Override detected optimal vector (1, 2 or 4) - one value or comma separated list"
) }
,
1480#endif
1481 OPT_WITHOUT_ARG("--verbose",{ ("--verbose"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_log_output) }, ("Log verbose output to stderr as well as status output"
) }
1482 opt_set_bool, &opt_log_output,{ ("--verbose"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_log_output) }, ("Log verbose output to stderr as well as status output"
) }
1483 "Log verbose output to stderr as well as status output"){ ("--verbose"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_log_output) }, ("Log verbose output to stderr as well as status output"
) }
,
1484#ifdef HAVE_OPENCL1
1485 OPT_WITH_ARG("--worksize|-w",{ ("--worksize|-w"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_worksize))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Override detected optimal worksize - one value or comma separated list"
) }
1486 set_worksize, NULL, NULL,{ ("--worksize|-w"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_worksize))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Override detected optimal worksize - one value or comma separated list"
) }
1487 "Override detected optimal worksize - one value or comma separated list"){ ("--worksize|-w"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_worksize))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Override detected optimal worksize - one value or comma separated list"
) }
,
1488#endif
1489 OPT_WITH_ARG("--userpass|-O",{ ("--userpass|-O"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_userpass))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Username:Password pair for bitcoin JSON-RPC server") }
1490 set_userpass, NULL, NULL,{ ("--userpass|-O"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_userpass))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Username:Password pair for bitcoin JSON-RPC server") }
1491 "Username:Password pair for bitcoin JSON-RPC server"){ ("--userpass|-O"), OPT_HASARG, ((void*)0), ((char *(*)(const
char *,void *))(((char *(*)(const char *,void *))(((char *(*
)(const char *,void *))((((set_userpass))))))))), ((void (*)(
char buf[], const void *))(((((void*)0))))), { (((void*)0)) }
, ("Username:Password pair for bitcoin JSON-RPC server") }
,
1492 OPT_WITHOUT_ARG("--worktime",{ ("--worktime"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_worktime) }, ("Display extra work time debug information"
) }
1493 opt_set_bool, &opt_worktime,{ ("--worktime"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_worktime) }, ("Display extra work time debug information"
) }
1494 "Display extra work time debug information"){ ("--worktime"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((opt_set_bool))))))))), ((void
*)0), ((void*)0), { (&opt_worktime) }, ("Display extra work time debug information"
) }
,
1495 OPT_WITH_ARG("--pools",{ ("--pools"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_bool))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, (opt_hidden
) }
1496 opt_set_bool, NULL, NULL, opt_hidden){ ("--pools"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((opt_set_bool))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, (opt_hidden
) }
,
1497 OPT_ENDTABLE{ ((void*)0), OPT_END, ((void*)0), ((void*)0), ((void*)0), { (
(void*)0) }, ((void*)0) }
1498};
1499
1500static char *load_config(const char *arg, void __maybe_unused__attribute__((unused)) *unused);
1501
1502static int fileconf_load;
1503
1504static char *parse_config(json_t *config, bool_Bool fileconf)
1505{
1506 static char err_buf[200];
1507 struct opt_table *opt;
1508 json_t *val;
1509
1510 if (fileconf && !fileconf_load)
1511 fileconf_load = 1;
1512
1513 for (opt = opt_config_table; opt->type != OPT_END; opt++) {
1514 char *p, *name, *sp;
1515
1516 /* We don't handle subtables. */
1517 assert(!(opt->type & OPT_SUBTABLE))((!(opt->type & OPT_SUBTABLE)) ? (void) (0) : __assert_fail
("!(opt->type & OPT_SUBTABLE)", "miner.c", 1517, __PRETTY_FUNCTION__
))
;
1518
1519 /* Pull apart the option name(s). */
1520 name = strdup(opt->names);
1521 for (p = strtok_r(name, "|", &sp); p; p = strtok_r(NULL((void*)0), "|", &sp)) {
1522 char *err = "Invalid value";
1523
1524 /* Ignore short options. */
1525 if (p[1] != '-')
1526 continue;
1527
1528 val = json_object_get(config, p+2);
1529 if (!val)
1530 continue;
1531
1532 if (opt->type & OPT_HASARG) {
1533 if (json_is_string(val)(val && ((val)->type) == JSON_STRING)) {
1534 err = opt->cb_arg(json_string_value(val),
1535 opt->u.arg);
1536 } else if (json_is_number(val)((val && ((val)->type) == JSON_INTEGER) || (val &&
((val)->type) == JSON_REAL))
) {
1537 char buf[256], *p, *q;
1538 snprintf(buf, 256, "%f", json_number_value(val));
1539 if ( (p = strchr(buf, '.')) ) {
1540 // Trim /\.0*$/ to work properly with integer-only arguments
1541 q = p;
1542 while (*(++q) == '0') {}
1543 if (*q == '\0')
1544 *p = '\0';
1545 }
1546 err = opt->cb_arg(buf, opt->u.arg);
1547 } else if (json_is_array(val)(val && ((val)->type) == JSON_ARRAY)) {
1548 int n, size = json_array_size(val);
1549
1550 err = NULL((void*)0);
1551 for (n = 0; n < size && !err; n++) {
1552 if (json_is_string(json_array_get(val, n))(json_array_get(val, n) && ((json_array_get(val, n))->
type) == JSON_STRING)
)
1553 err = opt->cb_arg(json_string_value(json_array_get(val, n)), opt->u.arg);
1554 else if (json_is_object(json_array_get(val, n))(json_array_get(val, n) && ((json_array_get(val, n))->
type) == JSON_OBJECT)
)
1555 err = parse_config(json_array_get(val, n), false0);
1556 }
1557 }
1558 } else if (opt->type & OPT_NOARG) {
1559 if (json_is_true(val)(val && ((val)->type) == JSON_TRUE))
1560 err = opt->cb(opt->u.arg);
1561 else if (json_is_boolean(val)((val && ((val)->type) == JSON_TRUE) || (val &&
((val)->type) == JSON_FALSE))
) {
1562 if (opt->cb == (void*)opt_set_bool)
1563 err = opt_set_invbool(opt->u.arg);
1564 else if (opt->cb == (void*)opt_set_invbool)
1565 err = opt_set_bool(opt->u.arg);
1566 }
1567 }
1568
1569 if (err) {
1570 /* Allow invalid values to be in configuration
1571 * file, just skipping over them provided the
1572 * JSON is still valid after that. */
1573 if (fileconf) {
1574 applog(LOG_ERR3, "Invalid config option %s: %s", p, err);
1575 fileconf_load = -1;
1576 } else {
1577 sprintf(err_buf, "Parsing JSON option %s: %s",
1578 p, err);
1579 return err_buf;
1580 }
1581 }
1582 }
1583 free(name);
1584 }
1585
1586 val = json_object_get(config, JSON_INCLUDE_CONF"include");
1587 if (val && json_is_string(val)(val && ((val)->type) == JSON_STRING))
1588 return load_config(json_string_value(val), NULL((void*)0));
1589
1590 return NULL((void*)0);
1591}
1592
1593char *cnfbuf = NULL((void*)0);
1594
1595static char *load_config(const char *arg, void __maybe_unused__attribute__((unused)) *unused)
1596{
1597 json_error_t err;
1598 json_t *config;
1599 char *json_error;
1600
1601 if (!cnfbuf)
1602 cnfbuf = strdup(arg);
1603
1604 if (++include_count > JSON_MAX_DEPTH10)
1605 return JSON_MAX_DEPTH_ERR"Too many levels of JSON includes (limit 10) or a loop";
1606
1607#if JANSSON_MAJOR_VERSION2 > 1
1608 config = json_load_file(arg, 0, &err);
1609#else
1610 config = json_load_file(arg, &err);
1611#endif
1612 if (!json_is_object(config)(config && ((config)->type) == JSON_OBJECT)) {
1613 json_error = malloc(JSON_LOAD_ERROR_LENstrlen("JSON decode of file '%s' failed\n %s") + strlen(arg) + strlen(err.text));
1614 if (!json_error)
1615 quit(1, "Malloc failure in json error");
1616
1617 sprintf(json_error, JSON_LOAD_ERROR"JSON decode of file '%s' failed\n %s", arg, err.text);
1618 return json_error;
1619 }
1620
1621 config_loaded = true1;
1622
1623 /* Parse the config now, so we can override it. That can keep pointers
1624 * so don't free config object. */
1625 return parse_config(config, true1);
1626}
1627
1628static void load_default_config(void)
1629{
1630 cnfbuf = malloc(PATH_MAX4096);
1631
1632#if defined(unix1)
1633 if (getenv("HOME") && *getenv("HOME")) {
1634 strcpy(cnfbuf, getenv("HOME"));
1635 strcat(cnfbuf, "/");
1636 } else
1637 strcpy(cnfbuf, "");
1638 char *dirp = cnfbuf + strlen(cnfbuf);
1639 strcpy(dirp, ".bfgminer/");
1640 strcat(dirp, def_conf);
1641 if (access(cnfbuf, R_OK4))
1642 // No BFGMiner config, try Cgminer's...
1643 strcpy(dirp, ".cgminer/cgminer.conf");
1644#else
1645 strcpy(cnfbuf, "");
1646 strcat(cnfbuf, def_conf);
1647#endif
1648 if (!access(cnfbuf, R_OK4))
1649 load_config(cnfbuf, NULL((void*)0));
1650 else {
1651 free(cnfbuf);
1652 cnfbuf = NULL((void*)0);
1653 }
1654}
1655
1656extern const char *opt_argv0;
1657
1658static char *opt_verusage_and_exit(const char *extra)
1659{
1660 printf("%s\nBuilt with "
1661#ifdef HAVE_OPENCL1
1662 "GPU "
1663#endif
1664#ifdef WANT_CPUMINE1
1665 "CPU "
1666#endif
1667#ifdef USE_BITFORCE1
1668 "bitforce "
1669#endif
1670#ifdef USE_ICARUS1
1671 "icarus "
1672#endif
1673#ifdef USE_AVALON1
1674 "avalon "
1675#endif
1676#ifdef USE_MODMINER1
1677 "modminer "
1678#endif
1679#ifdef USE_X65001
1680 "x6500 "
1681#endif
1682#ifdef USE_ZTEX1
1683 "ztex "
1684#endif
1685#ifdef USE_SCRYPT1
1686 "scrypt "
1687#endif
1688 "mining support.\n"
1689 , packagename);
1690 printf("%s", opt_usage(opt_argv0, extra));
1691 fflush(stdoutstdout);
1692 exit(0);
1693}
1694
1695/* These options are available from commandline only */
1696static struct opt_table opt_cmdline_table[] = {
1697 OPT_WITH_ARG("--config|-c",{ ("--config|-c"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((load_config))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Load a JSON-format configuration file\n"
"See example.conf for an example configuration.") }
1698 load_config, NULL, NULL,{ ("--config|-c"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((load_config))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Load a JSON-format configuration file\n"
"See example.conf for an example configuration.") }
1699 "Load a JSON-format configuration file\n"{ ("--config|-c"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((load_config))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Load a JSON-format configuration file\n"
"See example.conf for an example configuration.") }
1700 "See example.conf for an example configuration."){ ("--config|-c"), OPT_HASARG, ((void*)0), ((char *(*)(const char
*,void *))(((char *(*)(const char *,void *))(((char *(*)(const
char *,void *))((((load_config))))))))), ((void (*)(char buf
[], const void *))(((((void*)0))))), { (((void*)0)) }, ("Load a JSON-format configuration file\n"
"See example.conf for an example configuration.") }
,
1701 OPT_WITHOUT_ARG("--help|-h",{ ("--help|-h"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_verusage_and_exit)))))))
)), ((void*)0), ((void*)0), { (((void*)0)) }, ("Print this message"
) }
1702 opt_verusage_and_exit, NULL,{ ("--help|-h"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_verusage_and_exit)))))))
)), ((void*)0), ((void*)0), { (((void*)0)) }, ("Print this message"
) }
1703 "Print this message"){ ("--help|-h"), OPT_NOARG, ((char *(*)(void *))(((char *(*)(
void *))(((char *(*)(void *))((((opt_verusage_and_exit)))))))
)), ((void*)0), ((void*)0), { (((void*)0)) }, ("Print this message"
) }
,
1704#ifdef HAVE_OPENCL1
1705 OPT_WITHOUT_ARG("--ndevs|-n",{ ("--ndevs|-n"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((print_ndevs_and_exit)))))))
)), ((void*)0), ((void*)0), { (&nDevs) }, ("Display number of detected GPUs, OpenCL platform information, and exit"
) }
1706 print_ndevs_and_exit, &nDevs,{ ("--ndevs|-n"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((print_ndevs_and_exit)))))))
)), ((void*)0), ((void*)0), { (&nDevs) }, ("Display number of detected GPUs, OpenCL platform information, and exit"
) }
1707 "Display number of detected GPUs, OpenCL platform information, and exit"){ ("--ndevs|-n"), OPT_NOARG, ((char *(*)(void *))(((char *(*)
(void *))(((char *(*)(void *))((((print_ndevs_and_exit)))))))
)), ((void*)0), ((void*)0), { (&nDevs) }, ("Display number of detected GPUs, OpenCL platform information, and exit"
) }
,
1708#endif
1709 OPT_WITHOUT_ARG("--version|-V",{ ("--version|-V"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_version_and_exit)))))
)))), ((void*)0), ((void*)0), { (packagename) }, ("Display version and exit"
) }
1710 opt_version_and_exit, packagename,{ ("--version|-V"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_version_and_exit)))))
)))), ((void*)0), ((void*)0), { (packagename) }, ("Display version and exit"
) }
1711 "Display version and exit"){ ("--version|-V"), OPT_NOARG, ((char *(*)(void *))(((char *(
*)(void *))(((char *(*)(void *))((((opt_version_and_exit)))))
)))), ((void*)0), ((void*)0), { (packagename) }, ("Display version and exit"
) }
,
1712 OPT_ENDTABLE{ ((void*)0), OPT_END, ((void*)0), ((void*)0), ((void*)0), { (
(void*)0) }, ((void*)0) }
1713};
1714
1715static bool_Bool jobj_binary(const json_t *obj, const char *key,
1716 void *buf, size_t buflen, bool_Bool required)
1717{
1718 const char *hexstr;
1719 json_t *tmp;
1720
1721 tmp = json_object_get(obj, key);
1722 if (unlikely(!tmp)(!tmp)) {
1723 if (unlikely(required)(required))
1724 applog(LOG_ERR3, "JSON key '%s' not found", key);
1725 return false0;
1726 }
1727 hexstr = json_string_value(tmp);
1728 if (unlikely(!hexstr)(!hexstr)) {
1729 applog(LOG_ERR3, "JSON key '%s' is not a string", key);
1730 return false0;
1731 }
1732 if (!hex2bin(buf, hexstr, buflen))
1733 return false0;
1734
1735 return true1;
1736}
1737
1738static void calc_midstate(struct work *work)
1739{
1740 union {
1741 unsigned char c[64];
1742 uint32_t i[16];
1743 } data;
1744
1745 swap32yes(&data.i[0], work->data, 16);
1746 sha2_context ctx;
1747 sha2_starts(&ctx);
1748 sha2_update(&ctx, data.c, 64);
1749 memcpy(work->midstate, ctx.state, sizeof(work->midstate));
1750 swap32tole(work->midstate, work->midstate, 8)((work->midstate == work->midstate) ? (void)0 : memmove
(work->midstate, work->midstate, 8))
;
1751}
1752
1753static struct work *make_work(void)
1754{
1755 struct work *work = calloc(1, sizeof(struct work));
1756
1757 if (unlikely(!work)(!work))
1758 quit(1, "Failed to calloc work in make_work");
1759 mutex_lock(&control_lock);
1760 work->id = total_work++;
1761 mutex_unlock(&control_lock);
1762 return work;
1763}
1764
1765/* This is the central place all work that is about to be retired should be
1766 * cleaned to remove any dynamically allocated arrays within the struct */
1767void clean_work(struct work *work)
1768{
1769 free(work->job_id);
1770 free(work->nonce2);
1771 free(work->ntime);
1772 free(work->nonce1);
1773
1774 if (work->tmpl) {
1775 struct pool *pool = work->pool;
1776 mutex_lock(&pool->pool_lock);
1777 bool_Bool free_tmpl = !--*work->tmpl_refcount;
1778 mutex_unlock(&pool->pool_lock);
1779 if (free_tmpl) {
1780 blktmpl_free(work->tmpl);
1781 free(work->tmpl_refcount);
1782 }
1783 }
1784
1785 memset(work, 0, sizeof(struct work));
1786}
1787
1788/* All dynamically allocated work structs should be freed here to not leak any
1789 * ram from arrays allocated within the work struct */
1790void free_work(struct work *work)
1791{
1792 clean_work(work);
1793 free(work);
1794}
1795
1796static char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000";
1797
1798// Must only be called with ch_lock held!
1799static
1800void __update_block_title(const unsigned char *hash_swap)
1801{
1802 char *tmp;
1803 if (hash_swap) {
1804 // Only provided when the block has actually changed
1805 free(current_hash);
1806 current_hash = malloc(3 /* ... */ + 16 /* block hash segment */ + 1);
1807 tmp = bin2hex(&hash_swap[24], 8);
1808 sprintf(current_hash, "...%s", tmp);
1809 free(tmp);
1810 known_blkheight_current = false0;
1811 } else if (likely(known_blkheight_current)(known_blkheight_current)) {
1812 return;
1813 }
1814 if (current_block_id == known_blkheight_blkid) {
1815 // FIXME: The block number will overflow this sometime around AD 2025-2027
1816 if (known_blkheight < 1000000) {
1817 memmove(&current_hash[3], &current_hash[11], 8);
1818 sprintf(&current_hash[11], " #%6u", known_blkheight);
1819 }
1820 known_blkheight_current = true1;
1821 }
1822}
1823
1824static
1825void have_block_height(uint32_t block_id, uint32_t blkheight)
1826{
1827 if (known_blkheight == blkheight)
1828 return;
1829 applog(LOG_DEBUG7, "Learned that block id %08" PRIx32"x" " is height %" PRIu32"u", be32toh(block_id)(__extension__ ({ register unsigned int __v, __x = (block_id)
; if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
, blkheight);
1830 mutex_lock(&ch_lock);
1831 known_blkheight = blkheight;
1832 known_blkheight_blkid = block_id;
1833 if (block_id == current_block_id)
1834 __update_block_title(NULL((void*)0));
1835 mutex_unlock(&ch_lock);
1836}
1837
1838static bool_Bool work_decode(struct pool *pool, struct work *work, json_t *val)
1839{
1840 json_t *res_val = json_object_get(val, "result");
1841 json_t *tmp_val;
1842 bool_Bool ret = false0;
1843
1844 if (unlikely(detect_algo == 1)(detect_algo == 1)) {
1845 json_t *tmp = json_object_get(res_val, "algorithm");
1846 const char *v = tmp ? json_string_value(tmp) : "";
1847 if (strncasecmp(v, "scrypt", 6))
1848 detect_algo = 2;
1849 }
1850
1851 if (work->tmpl) {
1852 const char *err = blktmpl_add_jansson(work->tmpl, res_val, time(NULL((void*)0)));
1853 if (err) {
1854 applog(LOG_ERR3, "blktmpl error: %s", err);
1855 return false0;
1856 }
1857 work->rolltime = blkmk_time_left(work->tmpl, time(NULL((void*)0)));
1858#if BLKMAKER_VERSION(4L) > 1
1859 if (opt_coinbase_script.sz)
1860 {
1861 bool_Bool newcb;
1862#if BLKMAKER_VERSION(4L) > 2
1863 blkmk_init_generation2(work->tmpl, opt_coinbase_script.data, opt_coinbase_script.sz, &newcb);
1864#else
1865 newcb = !work->tmpl->cbtxn;
1866 blkmk_init_generation(work->tmpl, opt_coinbase_script.data, opt_coinbase_script.sz);
1867#endif
1868 if (newcb)
1869 {
1870 ssize_t ae = blkmk_append_coinbase_safe(work->tmpl, &template_nonce, sizeof(template_nonce));
1871 if (ae < (ssize_t)sizeof(template_nonce))
1872 applog(LOG_WARNING4, "Cannot append template-nonce to coinbase on pool %u (%"PRId64"ll" "d"") - you might be wasting hashing!", work->pool->pool_no, (int64_t)ae);
1873 ++template_nonce;
1874 }
1875 }
1876#endif
1877#if BLKMAKER_VERSION(4L) > 0
1878 {
1879 ssize_t ae = blkmk_append_coinbase_safe(work->tmpl, opt_coinbase_sig, 101);
1880 static bool_Bool appenderr = false0;
1881 if (ae <= 0) {
1882 if (opt_coinbase_sig) {
1883 applog((appenderr ? LOG_DEBUG7 : LOG_WARNING4), "Cannot append coinbase signature at all on pool %u (%"PRId64"ll" "d"")", pool->pool_no, (int64_t)ae);
1884 appenderr = true1;
1885 }
1886 } else if (ae >= 3 || opt_coinbase_sig) {
1887 const char *cbappend = opt_coinbase_sig;
1888 if (!cbappend) {
1889 const char full[] = PACKAGE"bfgminer" " " VERSION"3.0.0";
1890 // NOTE: Intentially including a trailing \0 on long forms so extranonce doesn't confuse things
1891 if ((size_t)ae >= sizeof(full))
1892 cbappend = full;
1893 else if ((size_t)ae >= sizeof(PACKAGE"bfgminer"))
1894 cbappend = PACKAGE"bfgminer";
1895 else
1896 cbappend = "BFG";
1897 }
1898 size_t cbappendsz = strlen(cbappend);
1899 static bool_Bool truncatewarning = false0;
1900 if (cbappendsz <= (size_t)ae) {
1901 ae = cbappendsz;
1902 truncatewarning = false0;
1903 } else {
1904 char *tmp = malloc(ae + 1);
1905 memcpy(tmp, opt_coinbase_sig, ae);
1906 tmp[ae] = '\0';
1907 applog((truncatewarning ? LOG_DEBUG7 : LOG_WARNING4),
1908 "Pool %u truncating appended coinbase signature at %"PRId64"ll" "d"" bytes: %s(%s)",
1909 pool->pool_no, (int64_t)ae, tmp, &opt_coinbase_sig[ae]);
1910 free(tmp);
1911 truncatewarning = true1;
1912 }
1913 ae = blkmk_append_coinbase_safe(work->tmpl, cbappend, ae);
1914 if (ae <= 0) {
1915 applog((appenderr ? LOG_DEBUG7 : LOG_WARNING4), "Error appending coinbase signature (%"PRId64"ll" "d"")", (int64_t)ae);
1916 appenderr = true1;
1917 } else
1918 appenderr = false0;
1919 }
1920 }
1921#endif
1922 if (blkmk_get_data(work->tmpl, work->data, 80, time(NULL((void*)0)), NULL((void*)0), &work->dataid) < 76)
1923 return false0;
1924 swap32yes(work->data, work->data, 80 / 4);
1925 memcpy(&work->data[80], "\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x80\x02\0\0", 48);
1926
1927 const struct blktmpl_longpoll_req *lp;
1928 if ((lp = blktmpl_get_longpoll(work->tmpl)) && ((!pool->lp_id) || strcmp(lp->id, pool->lp_id))) {
1929 free(pool->lp_id);
1930 pool->lp_id = strdup(lp->id);
1931
1932#if 0 /* This just doesn't work :( */
1933 curl_socket_t sock = pool->lp_socket;
1934 if (sock != CURL_SOCKET_BAD-1) {
1935 pool->lp_socket = CURL_SOCKET_BAD-1;
1936 applog(LOG_WARNING4, "Pool %u long poll request hanging, reconnecting", pool->pool_no);
1937 shutdown(sock, SHUT_RDWRSHUT_RDWR);
1938 }
1939#endif
1940 }
1941 }
1942 else
1943 if (unlikely(!jobj_binary(res_val, "data", work->data, sizeof(work->data), true))(!jobj_binary(res_val, "data", work->data, sizeof(work->
data), 1))
) {
1944 applog(LOG_ERR3, "JSON inval data");
1945 return false0;
1946 }
1947
1948 if (!jobj_binary(res_val, "midstate", work->midstate, sizeof(work->midstate), false0)) {
1949 // Calculate it ourselves
1950 applog(LOG_DEBUG7, "Calculating midstate locally");
1951 calc_midstate(work);
1952 }
1953
1954 if (unlikely(!jobj_binary(res_val, "target", work->target, sizeof(work->target), true))(!jobj_binary(res_val, "target", work->target, sizeof(work
->target), 1))
) {
1955 applog(LOG_ERR3, "JSON inval target");
1956 return false0;
1957 }
1958 if (work->tmpl) {
1959 for (size_t i = 0; i < sizeof(work->target) / 2; ++i)
1960 {
1961 int p = (sizeof(work->target) - 1) - i;
1962 unsigned char c = work->target[i];
1963 work->target[i] = work->target[p];
1964 work->target[p] = c;
1965 }
1966 }
1967
1968 if ( (tmp_val = json_object_get(res_val, "height")) ) {
1969 uint32_t blkheight = json_number_value(tmp_val);
1970 uint32_t block_id = ((uint32_t*)work->data)[1];
1971 have_block_height(block_id, blkheight);
1972 }
1973
1974 memset(work->hash, 0, sizeof(work->hash));
1975
1976 gettimeofday(&work->tv_staged, NULL((void*)0));
1977
1978 ret = true1;
1979
1980 return ret;
1981}
1982
1983int dev_from_id(int thr_id)
1984{
1985 return thr_info[thr_id].cgpu->device_id;
1986}
1987
1988/* Make the change in the recent value adjust dynamically when the difference
1989 * is large, but damp it when the values are closer together. This allows the
1990 * value to change quickly, but not fluctuate too dramatically when it has
1991 * stabilised. */
1992void decay_time(double *f, double fadd)
1993{
1994 double ratio = 0;
1995
1996 if (likely(*f > 0)(*f > 0)) {
1997 ratio = fadd / *f;
1998 if (ratio > 1)
1999 ratio = 1 / ratio;
2000 }
2001
2002 if (ratio > 0.63)
2003 *f = (fadd * 0.58 + *f) / 1.58;
2004 else
2005 *f = (fadd + *f * 0.58) / 1.58;
2006}
2007
2008static int __total_staged(void)
2009{
2010 return HASH_COUNT(staged_work)((staged_work)?((staged_work)->hh.tbl->num_items):0);
2011}
2012
2013static int total_staged(void)
2014{
2015 int ret;
2016
2017 mutex_lock(stgd_lock);
2018 ret = __total_staged();
2019 mutex_unlock(stgd_lock);
2020 return ret;
2021}
2022
2023#ifdef HAVE_CURSES1
2024WINDOW *mainwin, *statuswin, *logwin;
2025#endif
2026double total_secs = 1.0;
2027static char statusline[256];
2028/* logstart is where the log window should start */
2029static int devcursor, logstart, logcursor;
2030#ifdef HAVE_CURSES1
2031/* statusy is where the status window goes up to in cases where it won't fit at startup */
2032static int statusy;
2033static int devsummaryYOffset;
2034static int total_lines;
2035#endif
2036#ifdef HAVE_OPENCL1
2037struct cgpu_info gpus[MAX_GPUDEVICES16]; /* Maximum number apparently possible */
2038#endif
2039struct cgpu_info *cpus;
2040
2041#ifdef HAVE_CURSES1
2042static inline void unlock_curses(void)
2043{
2044 mutex_unlock(&console_lock);
2045}
2046
2047static inline void lock_curses(void)
2048{
2049 mutex_lock(&console_lock);
2050}
2051
2052static bool_Bool curses_active_locked(void)
2053{
2054 bool_Bool ret;
2055
2056 lock_curses();
2057 ret = curses_active;
2058 if (!ret)
2059 unlock_curses();
2060 return ret;
2061}
2062
2063// Cancellable getch
2064int my_cancellable_getch(void)
2065{
2066 // This only works because the macro only hits direct getch() calls
2067 typedef int (*real_getch_t)(void);
2068 const real_getch_t real_getch = __real_getch;
2069
2070 int type, rv;
2071 bool_Bool sct;
2072
2073 sct = !pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUSPTHREAD_CANCEL_ASYNCHRONOUS, &type);
2074 rv = real_getch();
2075 if (sct)
2076 pthread_setcanceltype(type, &type);
2077
2078 return rv;
2079}
2080#endif
2081
2082void tailsprintf(char *f, const char *fmt, ...)
2083{
2084 va_list ap;
2085
2086 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2087 vsprintf(f + strlen(f), fmt, ap);
2088 va_end(ap)__builtin_va_end(ap);
2089}
2090
2091/* Convert a uint64_t value into a truncated string for displaying with its
2092 * associated suitable for Mega, Giga etc. Buf array needs to be long enough */
2093static void suffix_string(uint64_t val, char *buf, int sigdigits)
2094{
2095 const double dkilo = 1000.0;
2096 const uint64_t kilo = 1000ull;
2097 const uint64_t mega = 1000000ull;
2098 const uint64_t giga = 1000000000ull;
2099 const uint64_t tera = 1000000000000ull;
2100 const uint64_t peta = 1000000000000000ull;
2101 const uint64_t exa = 1000000000000000000ull;
2102 char suffix[2] = "";
2103 bool_Bool decimal = true1;
2104 double dval;
2105
2106 if (val >= exa) {
2107 val /= peta;
2108 dval = (double)val / dkilo;
2109 sprintf(suffix, "E");
2110 } else if (val >= peta) {
2111 val /= tera;
2112 dval = (double)val / dkilo;
2113 sprintf(suffix, "P");
2114 } else if (val >= tera) {
2115 val /= giga;
2116 dval = (double)val / dkilo;
2117 sprintf(suffix, "T");
2118 } else if (val >= giga) {
2119 val /= mega;
2120 dval = (double)val / dkilo;
2121 sprintf(suffix, "G");
2122 } else if (val >= mega) {
2123 val /= kilo;
2124 dval = (double)val / dkilo;
2125 sprintf(suffix, "M");
2126 } else if (val >= kilo) {
2127 dval = (double)val / dkilo;
2128 sprintf(suffix, "k");
2129 } else {
2130 dval = val;
2131 decimal = false0;
2132 }
2133
2134 if (!sigdigits) {
2135 if (decimal)
2136 sprintf(buf, "%.3g%s", dval, suffix);
2137 else
2138 sprintf(buf, "%d%s", (unsigned int)dval, suffix);
2139 } else {
2140 /* Always show sigdigits + 1, padded on right with zeroes
2141 * followed by suffix */
2142 int ndigits = sigdigits - 1 - (dval > 0.0 ? floor(log10(dval)) : 0);
2143
2144 sprintf(buf, "%*.*f%s", sigdigits + 1, ndigits, dval, suffix);
2145 }
2146}
2147
2148static float
2149utility_to_hashrate(double utility)
2150{
2151 return utility * 0x4444444;
2152}
2153
2154static const char*_unitchar = "kMGTPEZY?";
2155
2156static void
2157hashrate_pick_unit(float hashrate, unsigned char*unit)
2158{
2159 unsigned char i;
2160 for (i = 0; i <= *unit; ++i)
2161 hashrate /= 1e3;
2162 while (hashrate >= 1000)
2163 {
2164 hashrate /= 1e3;
2165 if (likely(_unitchar[*unit] != '?')(_unitchar[*unit] != '?'))
2166 ++*unit;
2167 }
2168}
2169
2170enum h2bs_fmt {
2171 H2B_NOUNIT, // "xxx.x"
2172 H2B_SHORT, // "xxx.xMH/s"
2173 H2B_SPACED, // "xxx.x MH/s"
2174};
2175static const size_t h2bs_fmt_size[] = {6, 10, 11};
2176
2177static char*
2178hashrate_to_bufstr(char*buf, float hashrate, signed char unitin, enum h2bs_fmt fmt)
2179{
2180 unsigned char prec, i, ucp, unit;
2181 if (unitin == -1)
2182 {
2183 unit = 0;
2184 hashrate_pick_unit(hashrate, &unit);
2185 }
2186 else
2187 unit = unitin;
2188
2189 i = 5;
2190 switch (fmt) {
2191 case H2B_SPACED:
2192 buf[i++] = ' ';
2193 case H2B_SHORT:
2194 buf[i++] = _unitchar[unit];
2195 strcpy(&buf[i], "h/s");
2196 default:
2197 break;
2198 }
2199
2200 for (i = 0; i <= unit; ++i)
2201 hashrate /= 1000;
2202 if (hashrate >= 100 || unit < 2)
2203 prec = 1;
2204 else
2205 if (hashrate >= 10)
2206 prec = 2;
2207 else
2208 prec = 3;
2209 ucp = (fmt == H2B_NOUNIT ? '\0' : buf[5]);
2210 sprintf(buf, "%5.*f", prec, hashrate);
2211 buf[5] = ucp;
2212 return buf;
2213}
2214
2215static void
2216ti_hashrate_bufstr(char**out, float current, float average, float sharebased, enum h2bs_fmt longfmt)
2217{
2218 unsigned char unit = 0;
2219
2220 hashrate_pick_unit(current, &unit);
2221 hashrate_pick_unit(average, &unit);
2222 hashrate_pick_unit(sharebased, &unit);
2223
2224 hashrate_to_bufstr(out[0], current, unit, H2B_NOUNIT);
2225 hashrate_to_bufstr(out[1], average, unit, H2B_NOUNIT);
2226 hashrate_to_bufstr(out[2], sharebased, unit, longfmt);
2227}
2228
2229#ifdef HAVE_CURSES1
2230static void adj_width(int var, int *length);
2231#endif
2232
2233static void get_statline2(char *buf, struct cgpu_info *cgpu, bool_Bool for_curses)
2234{
2235#ifdef HAVE_CURSES1
2236 static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1;
2237#else
2238 assert(for_curses == false)((for_curses == 0) ? (void) (0) : __assert_fail ("for_curses == 0"
, "miner.c", 2238, __PRETTY_FUNCTION__))
;
2239#endif
2240 const struct device_api *api = cgpu->api;
2241 void (*statline_func)(char *, struct cgpu_info *);
2242 enum h2bs_fmt hashrate_style = for_curses ? H2B_SHORT : H2B_SPACED;
2243 char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[hashrate_style]];
2244
2245 if (!opt_show_procs)
2246 cgpu = cgpu->device;
2247
2248 cgpu->utility = cgpu->accepted / total_secs * 60;
2249 cgpu->utility_diff1 = cgpu->diff_accepted / total_secs * 60;
2250
2251 double rolling = cgpu->rolling;
2252 double mhashes = cgpu->total_mhashes;
2253 double wutil = cgpu->utility_diff1;
2254 int accepted = cgpu->accepted;
2255 int rejected = cgpu->rejected;
2256 int hwerrs = cgpu->hw_errors;
2257 double util = cgpu->utility;
2258
2259 if (!opt_show_procs)
2260 for (struct cgpu_info *slave = cgpu; (slave = slave->next_proc); )
2261 {
2262 slave->utility = slave->accepted / total_secs * 60;
2263 slave->utility_diff1 = slave->diff_accepted / total_secs * 60;
2264
2265 rolling += slave->rolling;
2266 mhashes += slave->total_mhashes;
2267 wutil += slave->utility_diff1;
2268 accepted += slave->accepted;
2269 rejected += slave->rejected;
2270 hwerrs += slave->hw_errors;
2271 util += slave->utility;
2272 }
2273
2274 ti_hashrate_bufstr(
2275 (char*[]){cHr, aHr, uHr},
2276 1e6*rolling,
2277 1e6*mhashes / total_secs,
2278 utility_to_hashrate(wutil),
2279 hashrate_style);
2280
2281 // Processor representation
2282#ifdef HAVE_CURSES1
2283 if (for_curses)
2284 {
2285 if (opt_show_procs)
2286 sprintf(buf, " %"PRIprepr"-6s"": ", cgpu->proc_repr);
2287 else
2288 sprintf(buf, " %s: ", cgpu->dev_repr);
2289 }
2290 else
2291#endif
2292 sprintf(buf, "%s ", opt_show_procs ? cgpu->proc_repr_ns : cgpu->dev_repr_ns);
2293
2294 if (api->get_dev_statline_before || api->get_statline_before)
2295 {
2296 if (api->get_dev_statline_before && api->get_statline_before)
2297 statline_func = opt_show_procs ? api->get_statline_before : api->get_dev_statline_before;
2298 else
2299 statline_func = api->get_statline_before ?: api->get_dev_statline_before;
2300 statline_func(buf, cgpu);
2301 }
2302 else
2303 tailsprintf(buf, " | ");
2304
2305#ifdef HAVE_CURSES1
2306 if (for_curses)
2307 {
2308 const char *cHrStatsOpt[] = {"DEAD ", "SICK ", "OFF ", "REST ", " ERR ", "WAIT ", cHr};
2309 int cHrStatsI = (sizeof(cHrStatsOpt) / sizeof(*cHrStatsOpt)) - 1;
2310 bool_Bool all_dead = true1, all_off = true1;
2311 for (struct cgpu_info *proc = cgpu; proc; proc = proc->next_proc)
2312 {
2313 switch (cHrStatsI) {
2314 default:
2315 if (proc->status == LIFE_WAIT)
2316 cHrStatsI = 5;
2317 case 5:
2318 if (proc->deven == DEV_RECOVER_ERR)
2319 cHrStatsI = 4;
2320 case 4:
2321 if (proc->deven == DEV_RECOVER)
2322 cHrStatsI = 3;
2323 case 3:
2324 if (proc->status == LIFE_SICK || proc->status == LIFE_DEAD)
2325 {
2326 cHrStatsI = 1;
2327 all_off = false0;
2328 }
2329 else
2330 if (likely(proc->deven != DEV_DISABLED)(proc->deven != DEV_DISABLED))
2331 all_off = false0;
2332 case 1:
2333 break;
2334 }
2335 if (likely(proc->status != LIFE_DEAD)(proc->status != LIFE_DEAD))
2336 all_dead = false0;
2337 if (opt_show_procs)
2338 break;
2339 }
2340 if (unlikely(all_dead)(all_dead))
2341 cHrStatsI = 0;
2342 else
2343 if (unlikely(all_off)(all_off))
2344 cHrStatsI = 2;
2345
2346 adj_width(accepted, &awidth);
2347 adj_width(rejected, &rwidth);
2348 adj_width(hwerrs, &hwwidth);
2349 adj_width(util, &uwidth);
2350
2351 tailsprintf(buf, "%s/%s/%s | A:%*d R:%*d HW:%*d U:%*.2f/m",
2352 cHrStatsOpt[cHrStatsI],
2353 aHr, uHr,
2354 awidth, accepted,
2355 rwidth, rejected,
2356 hwwidth, hwerrs,
2357 uwidth + 3, util
2358 );
2359 }
2360 else
2361#endif
2362 {
2363 tailsprintf(buf, "%ds:%s avg:%s u:%s | A:%d R:%d HW:%d U:%.1f/m",
2364 opt_log_interval,
2365 cHr, aHr, uHr,
2366 accepted,
2367 rejected,
2368 hwerrs,
2369 util);
2370 }
2371
2372 if (api->get_dev_statline_after || api->get_statline)
2373 {
2374 if (api->get_dev_statline_after && api->get_statline)
2375 statline_func = opt_show_procs ? api->get_statline : api->get_dev_statline_after;
2376 else
2377 statline_func = api->get_statline ?: api->get_dev_statline_after;
2378 statline_func(buf, cgpu);
2379 }
2380}
2381
2382#define get_statline(buf, cgpu)get_statline2(buf, cgpu, 0) get_statline2(buf, cgpu, false0)
2383
2384static void text_print_status(int thr_id)
2385{
2386 struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
2387 char logline[256];
2388
2389 if (cgpu) {
2390 get_statline(logline, cgpu)get_statline2(logline, cgpu, 0);
2391 printf("%s\n", logline);
2392 }
2393}
2394
2395#ifdef HAVE_CURSES1
2396/* Must be called with curses mutex lock held and curses_active */
2397static void curses_print_status(void)
2398{
2399 struct pool *pool = current_pool();
2400 struct timeval now, tv;
2401 float efficiency;
2402
2403 efficiency = total_bytes_xfer ? total_diff_accepted * 2048. / total_bytes_xfer : 0.0;
2404
2405 wattron(statuswin, A_BOLD)wattr_on(statuswin, (attr_t)(((1UL) << ((13) + 8))), ((
void*)0))
;
2406 mvwprintw(statuswin, 0, 0, " " PACKAGE"bfgminer" " version " VERSION"3.0.0" " - Started: %s", datestamp);
2407 if (!gettimeofday(&now, NULL((void*)0)))
2408 {
2409 unsigned int days, hours;
2410 div_t d;
2411
2412 timersub(&now, &miner_started, &tv)do { (&tv)->tv_sec = (&now)->tv_sec - (&miner_started
)->tv_sec; (&tv)->tv_usec = (&now)->tv_usec -
(&miner_started)->tv_usec; if ((&tv)->tv_usec <
0) { --(&tv)->tv_sec; (&tv)->tv_usec += 1000000
; } } while (0)
;
2413 d = div(tv.tv_sec, 86400);
2414 days = d.quot;
2415 d = div(d.rem, 3600);
2416 hours = d.quot;
2417 d = div(d.rem, 60);
2418 wprintw(statuswin, " - [%3u day%c %02d:%02d:%02d]"
2419 , days
2420 , (days == 1) ? ' ' : 's'
2421 , hours
2422 , d.quot
2423 , d.rem
2424 );
2425 }
2426 wattroff(statuswin, A_BOLD)wattr_off(statuswin, (attr_t)(((1UL) << ((13) + 8))), (
(void*)0))
;
2427 mvwhline(statuswin, 1, 0, '-', 80)(wmove(statuswin,1,0) == (-1) ? (-1) : whline(statuswin,'-',80
))
;
2428 mvwprintw(statuswin, 2, 0, " %s", statusline);
2429 wclrtoeol(statuswin);
2430 mvwprintw(statuswin, 3, 0, " ST: %d DW: %d GW: %d LW: %d GF: %d NB: %d AS: %d RF: %d E: %.2f",
2431 total_staged(), total_discarded,
2432 total_getworks,
2433 local_work,
2434 total_go,
2435 new_blocks,
2436 total_submitting,
2437 total_ro,
2438 efficiency);
2439 wclrtoeol(statuswin);
2440 if ((pool_strategy == POOL_LOADBALANCE || pool_strategy == POOL_BALANCE) && total_pools > 1) {
2441 mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP",
2442 have_longpoll ? "": "out");
2443 } else if (pool->has_stratum) {
2444 mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with stratum as user %s",
2445 pool->sockaddr_url, pool->diff, pool->rpc_user);
2446 } else {
2447 mvwprintw(statuswin, 4, 0, " Connected to %s diff %s with%s LP as user %s",
2448 pool->sockaddr_url, pool->diff, have_longpoll ? "": "out", pool->rpc_user);
2449 }
2450 wclrtoeol(statuswin);
2451 mvwprintw(statuswin, 5, 0, " Block: %s Diff:%s (%s) Started: %s",
2452 current_hash, block_diff, net_hashrate, blocktime);
2453 mvwhline(statuswin, 6, 0, '-', 80)(wmove(statuswin,6,0) == (-1) ? (-1) : whline(statuswin,'-',80
))
;
2454 mvwhline(statuswin, statusy - 1, 0, '-', 80)(wmove(statuswin,statusy - 1,0) == (-1) ? (-1) : whline(statuswin
,'-',80))
;
2455 mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit",
2456 have_opencl ? "[G]PU management " : "");
2457}
2458
2459static void adj_width(int var, int *length)
2460{
2461 if ((int)(log10(var) + 1) > *length)
2462 (*length)++;
2463}
2464
2465static int dev_width;
2466
2467static void curses_print_devstatus(int thr_id)
2468{
2469 struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
2470 char logline[256];
2471 int ypos;
2472
2473 if (opt_compact)
2474 return;
2475
2476 /* Check this isn't out of the window size */
2477 if (opt_show_procs)
2478 ypos = cgpu->cgminer_id;
2479 else
2480 {
2481 if (cgpu->proc_id)
2482 return;
2483 ypos = cgpu->device_line_id;
2484 }
2485 ypos += devsummaryYOffset;
2486 if (ypos < 0)
2487 return;
2488 ypos += devcursor;
2489 if (ypos >= statusy - 1)
2490 return;
2491
2492 if (wmove(statuswin, ypos, 0) == ERR(-1))
2493 return;
2494
2495 get_statline2(logline, cgpu, true1);
2496 waddstr(statuswin, logline)waddnstr(statuswin,logline,-1);
2497
2498 wclrtoeol(statuswin);
2499}
2500#endif
2501
2502static void print_status(int thr_id)
2503{
2504 if (!curses_active)
2505 text_print_status(thr_id);
2506}
2507
2508#ifdef HAVE_CURSES1
2509/* Check for window resize. Called with curses mutex locked */
2510static inline void change_logwinsize(void)
2511{
2512 int x, y, logx, logy;
2513
2514 getmaxyx(mainwin, y, x)(y = ((mainwin) ? ((mainwin)->_maxy + 1) : (-1)), x = ((mainwin
) ? ((mainwin)->_maxx + 1) : (-1)))
;
2515 if (x < 80 || y < 25)
2516 return;
2517
2518 if (y > statusy + 2 && statusy < logstart) {
2519 if (y - 2 < logstart)
2520 statusy = y - 2;
2521 else
2522 statusy = logstart;
2523 logcursor = statusy + 1;
2524 mvwin(logwin, logcursor, 0);
2525 wresize(statuswin, statusy, x);
2526 }
2527
2528 y -= logcursor;
2529 getmaxyx(logwin, logy, logx)(logy = ((logwin) ? ((logwin)->_maxy + 1) : (-1)), logx = (
(logwin) ? ((logwin)->_maxx + 1) : (-1)))
;
2530 /* Detect screen size change */
2531 if (x != logx || y != logy)
2532 wresize(logwin, y, x);
2533}
2534
2535static void check_winsizes(void)
2536{
2537 if (!use_curses)
2538 return;
2539 if (curses_active_locked()) {
2540 int y, x;
2541
2542 erase()werase(stdscr);
2543 x = getmaxx(statuswin)((statuswin) ? ((statuswin)->_maxx + 1) : (-1));
2544 if (logstart > LINES - 2)
2545 statusy = LINES - 2;
2546 else
2547 statusy = logstart;
2548 logcursor = statusy + 1;
2549 wresize(statuswin, statusy, x);
2550 getmaxyx(mainwin, y, x)(y = ((mainwin) ? ((mainwin)->_maxy + 1) : (-1)), x = ((mainwin
) ? ((mainwin)->_maxx + 1) : (-1)))
;
2551 y -= logcursor;
2552 wresize(logwin, y, x);
2553 mvwin(logwin, logcursor, 0);
2554 unlock_curses();
2555 }
2556}
2557
2558static int device_line_id_count;
2559
2560static void switch_compact(void)
2561{
2562 if (opt_compact) {
2563 logstart = devcursor + 1;
2564 logcursor = logstart + 1;
2565 } else {
2566 total_lines = (opt_show_procs ? total_devices : device_line_id_count);
2567 logstart = devcursor + total_lines + 1;
2568 logcursor = logstart + 1;
2569 }
2570 check_winsizes();
2571}
2572
2573#define change_summarywinsizeswitch_compact switch_compact
2574
2575/* For mandatory printing when mutex is already locked */
2576void wlog(const char *f, ...)
2577{
2578 va_list ap;
2579
2580 va_start(ap, f)__builtin_va_start(ap, f);
2581 vw_printwvwprintw(logwin, f, ap);
2582 va_end(ap)__builtin_va_end(ap);
2583}
2584
2585/* Mandatory printing */
2586void wlogprint(const char *f, ...)
2587{
2588 va_list ap;
2589
2590 if (curses_active_locked()) {
2591 va_start(ap, f)__builtin_va_start(ap, f);
2592 vw_printwvwprintw(logwin, f, ap);
2593 va_end(ap)__builtin_va_end(ap);
2594 unlock_curses();
2595 }
2596}
2597#endif
2598
2599#ifdef HAVE_CURSES1
2600bool_Bool log_curses_only(int prio, const char *f, va_list ap)
2601{
2602 bool_Bool high_prio;
2603
2604 high_prio = (prio == LOG_WARNING4 || prio == LOG_ERR3);
2605
2606 if (curses_active_locked()) {
2607 if (!opt_loginput || high_prio) {
2608 vw_printwvwprintw(logwin, f, ap);
2609 if (high_prio) {
2610 touchwin(logwin)wtouchln((logwin), 0, ((logwin) ? ((logwin)->_maxy + 1) : (
-1)), 1)
;
2611 wrefresh(logwin);
2612 }
2613 }
2614 unlock_curses();
2615 return true1;
2616 }
2617 return false0;
2618}
2619
2620void clear_logwin(void)
2621{
2622 if (curses_active_locked()) {
2623 wclear(logwin);
2624 unlock_curses();
2625 }
2626}
2627#endif
2628
2629/* Returns true if the regenerated work->hash solves a block */
2630static bool_Bool solves_block(const struct work *work)
2631{
2632 unsigned char target[32];
2633
2634 real_block_target(target, work->data);
2635 return hash_target_check(work->hash, target);
2636}
2637
2638static void enable_pool(struct pool *pool)
2639{
2640 if (pool->enabled != POOL_ENABLED) {
2641 enabled_pools++;
2642 pool->enabled = POOL_ENABLED;
2643 }
2644}
2645
2646static void disable_pool(struct pool *pool)
2647{
2648 if (pool->enabled == POOL_ENABLED)
2649 enabled_pools--;
2650 pool->enabled = POOL_DISABLED;
2651}
2652
2653static void reject_pool(struct pool *pool)
2654{
2655 if (pool->enabled == POOL_ENABLED)
2656 enabled_pools--;
2657 pool->enabled = POOL_REJECTING;
2658}
2659
2660static uint64_t share_diff(const struct work *);
2661
2662static
2663void share_result_msg(const struct work *work, const char *disp, const char *reason, bool_Bool resubmit, const char *worktime) {
2664 struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu;
2665 const unsigned char *hashpart = &work->hash[opt_scrypt ? 26 : 24];
2666 uint64_t shrdiff = share_diff(work);
2667 char shrdiffdisp[16];
2668 int tgtdiff = floor(work->work_difficulty);
2669 char tgtdiffdisp[16];
2670 char where[20];
2671
2672 suffix_string(shrdiff, shrdiffdisp, 0);
2673 suffix_string(tgtdiff, tgtdiffdisp, 0);
2674
2675 if (total_pools > 1)
2676 sprintf(where, " pool %d", work->pool->pool_no);
2677 else
2678 where[0] = '\0';
2679
2680 applog(LOG_NOTICE5, "%s %02x%02x%02x%02x %"PRIprepr"-6s""%s Diff %s/%s%s %s%s",
2681 disp,
2682 (unsigned)hashpart[3], (unsigned)hashpart[2], (unsigned)hashpart[1], (unsigned)hashpart[0],
2683 cgpu->proc_repr,
2684 where,
2685 shrdiffdisp, tgtdiffdisp,
2686 reason,
2687 resubmit ? "(resubmit)" : "",
2688 worktime
2689 );
2690}
2691
2692static bool_Bool test_work_current(struct work *);
2693static void _submit_work_async(struct work *);
2694
2695static
2696void maybe_local_submit(const struct work *work)
2697{
2698#if BLKMAKER_VERSION(4L) > 3
2699 if (unlikely(work->block && work->tmpl)(work->block && work->tmpl))
2700 {
2701 // This is a block with a full template (GBT)
2702 // Regardless of the result, submit to local bitcoind(s) as well
2703 struct work *work_cp;
2704 char *p;
2705
2706 for (int i = 0; i < total_pools; ++i)
2707 {
2708 p = strchr(pools[i]->rpc_url, '#');
2709 if (likely(!(p && strstr(&p[1], "allblocks")))(!(p && strstr(&p[1], "allblocks"))))
2710 continue;
2711
2712 work_cp = copy_work(work);
2713 work_cp->pool = pools[i];
2714 work_cp->do_foreign_submit = true1;
2715 _submit_work_async(work_cp);
2716 }
2717 }
2718#endif
2719}
2720
2721/* Theoretically threads could race when modifying accepted and
2722 * rejected values but the chance of two submits completing at the
2723 * same time is zero so there is no point adding extra locking */
2724static void
2725share_result(json_t *val, json_t *res, json_t *err, const struct work *work,
2726 /*char *hashshow,*/ bool_Bool resubmit, char *worktime)
2727{
2728 struct pool *pool = work->pool;
2729 struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu;
2730
2731 if ((json_is_null(err)(err && ((err)->type) == JSON_NULL) || !err) && (json_is_null(res)(res && ((res)->type) == JSON_NULL) || json_is_true(res)(res && ((res)->type) == JSON_TRUE))) {
2732 mutex_lock(&stats_lock);
2733 cgpu->accepted++;
2734 total_accepted++;
2735 pool->accepted++;
2736 cgpu->diff_accepted += work->work_difficulty;
2737 total_diff_accepted += work->work_difficulty;
2738 pool->diff_accepted += work->work_difficulty;
2739 mutex_unlock(&stats_lock);
2740
2741 pool->seq_rejects = 0;
2742 cgpu->last_share_pool = pool->pool_no;
2743 cgpu->last_share_pool_time = time(NULL((void*)0));
2744 cgpu->last_share_diff = work->work_difficulty;
2745 pool->last_share_time = cgpu->last_share_pool_time;
2746 pool->last_share_diff = work->work_difficulty;
2747 applog(LOG_DEBUG7, "PROOF OF WORK RESULT: true (yay!!!)");
2748 if (!QUIET(opt_quiet || opt_realquiet)) {
2749 share_result_msg(work, "Accepted", "", resubmit, worktime);
2750 }
2751 sharelog("accept", work);
2752 if (opt_shares && total_accepted >= opt_shares) {
2753 applog(LOG_WARNING4, "Successfully mined %d accepted shares as requested and exiting.", opt_shares);
2754 kill_work();
2755 return;
2756 }
2757
2758 /* Detect if a pool that has been temporarily disabled for
2759 * continually rejecting shares has started accepting shares.
2760 * This will only happen with the work returned from a
2761 * longpoll */
2762 if (unlikely(pool->enabled == POOL_REJECTING)(pool->enabled == POOL_REJECTING)) {
2763 applog(LOG_WARNING4, "Rejecting pool %d now accepting shares, re-enabling!", pool->pool_no);
2764 enable_pool(pool);
2765 switch_pools(NULL((void*)0));
2766 }
2767
2768 if (unlikely(work->block)(work->block)) {
2769 // Force moving on to this new block :)
2770 struct work fakework;
2771 memset(&fakework, 0, sizeof(fakework));
2772 fakework.pool = work->pool;
2773
2774 // Copy block version, bits, and time from share
2775 memcpy(&fakework.data[ 0], &work->data[ 0], 4);
2776 memcpy(&fakework.data[68], &work->data[68], 8);
2777
2778 // Set prevblock to winning hash (swap32'd)
2779 swap32yes(&fakework.data[4], &work->hash[0], 32 / 4);
2780
2781 test_work_current(&fakework);
2782 }
2783 } else {
2784 mutex_lock(&stats_lock);
2785 cgpu->rejected++;
2786 total_rejected++;
2787 pool->rejected++;
2788 cgpu->diff_rejected += work->work_difficulty;
2789 total_diff_rejected += work->work_difficulty;
2790 pool->diff_rejected += work->work_difficulty;
2791 pool->seq_rejects++;
2792 mutex_unlock(&stats_lock);
2793
2794 applog(LOG_DEBUG7, "PROOF OF WORK RESULT: false (booooo)");
2795 if (!QUIET(opt_quiet || opt_realquiet)) {
2796 char where[20];
2797 char disposition[36] = "reject";
2798 char reason[32];
2799
2800 strcpy(reason, "");
2801 if (total_pools > 1)
2802 sprintf(where, "pool %d", work->pool->pool_no);
2803 else
2804 strcpy(where, "");
2805
2806 if (!json_is_string(res)(res && ((res)->type) == JSON_STRING))
2807 res = json_object_get(val, "reject-reason");
2808 if (res) {
2809 const char *reasontmp = json_string_value(res);
2810
2811 size_t reasonLen = strlen(reasontmp);
2812 if (reasonLen > 28)
2813 reasonLen = 28;
2814 reason[0] = ' '; reason[1] = '(';
2815 memcpy(2 + reason, reasontmp, reasonLen);
2816 reason[reasonLen + 2] = ')'; reason[reasonLen + 3] = '\0';
2817 memcpy(disposition + 7, reasontmp, reasonLen);
2818 disposition[6] = ':'; disposition[reasonLen + 7] = '\0';
2819 } else if (work->stratum && err && json_is_array(err)(err && ((err)->type) == JSON_ARRAY)) {
2820 json_t *reason_val = json_array_get(err, 1);
2821 char *reason_str;
2822
2823 if (reason_val && json_is_string(reason_val)(reason_val && ((reason_val)->type) == JSON_STRING
)
) {
2824 reason_str = (char *)json_string_value(reason_val);
2825 snprintf(reason, 31, " (%s)", reason_str);
2826 }
2827 }
2828
2829 share_result_msg(work, "Rejected", reason, resubmit, worktime);
2830 sharelog(disposition, work);
2831 }
2832
2833 /* Once we have more than a nominal amount of sequential rejects,
2834 * at least 10 and more than 3 mins at the current utility,
2835 * disable the pool because some pool error is likely to have
2836 * ensued. Do not do this if we know the share just happened to
2837 * be stale due to networking delays.
2838 */
2839 if (pool->seq_rejects > 10 && !work->stale && opt_disable_pool && enabled_pools > 1) {
2840 double utility = total_accepted / total_secs * 60;
2841
2842 if (pool->seq_rejects > utility * 3) {
2843 applog(LOG_WARNING4, "Pool %d rejected %d sequential shares, disabling!",
2844 pool->pool_no, pool->seq_rejects);
2845 reject_pool(pool);
2846 if (pool == current_pool())
2847 switch_pools(NULL((void*)0));
2848 pool->seq_rejects = 0;
2849 }
2850 }
2851 }
2852
2853 maybe_local_submit(work);
2854}
2855
2856static const uint64_t diffone = 0xFFFF000000000000ull;
2857
2858static double target_diff(const unsigned char *target);
2859
2860static uint64_t share_diff(const struct work *work)
2861{
2862 uint64_t ret;
2863
2864 ret = target_diff(work->hash);
2865 mutex_lock(&control_lock);
2866 if (ret > best_diff) {
2867 best_diff = ret;
2868 suffix_string(best_diff, best_share, 0);
2869 }
2870 if (ret > work->pool->best_diff)
2871 work->pool->best_diff = ret;
2872 mutex_unlock(&control_lock);
2873 return ret;
2874}
2875
2876static char *submit_upstream_work_request(struct work *work)
2877{
2878 char *hexstr = NULL((void*)0);
2879 char *s, *sd;
2880 struct pool *pool = work->pool;
2881
2882 if (work->tmpl) {
2883 json_t *req;
2884 unsigned char data[80];
2885
2886 swap32yes(data, work->data, 80 / 4);
2887#if BLKMAKER_VERSION(4L) > 3
2888 if (work->do_foreign_submit)
2889 req = blkmk_submit_foreign_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76]))(*((uint32_t*)&work->data[76])));
2890 else
2891#endif
2892 req = blkmk_submit_jansson(work->tmpl, data, work->dataid, le32toh(*((uint32_t*)&work->data[76]))(*((uint32_t*)&work->data[76])));
2893 s = json_dumps(req, 0);
2894 json_decref(req);
2895 sd = bin2hex(data, 80);
2896 } else {
2897
2898 /* build hex string */
2899 hexstr = bin2hex(work->data, sizeof(work->data));
2900
2901 /* build JSON-RPC request */
2902 s = strdup("{\"method\": \"getwork\", \"params\": [ \"");
2903 s = realloc_strcat(s, hexstr);
2904 s = realloc_strcat(s, "\" ], \"id\":1}");
2905
2906 free(hexstr);
2907 sd = s;
2908
2909 }
2910
2911 applog(LOG_DEBUG7, "DBG: sending %s submit RPC call: %s", pool->rpc_url, sd);
2912 if (work->tmpl)
2913 free(sd);
2914 else
2915 s = realloc_strcat(s, "\n");
2916
2917 return s;
2918}
2919
2920static bool_Bool submit_upstream_work_completed(struct work *work, bool_Bool resubmit, struct timeval *ptv_submit, json_t *val) {
2921 json_t *res, *err;
2922 bool_Bool rc = false0;
2923 int thr_id = work->thr_id;
2924 struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
2925 struct pool *pool = work->pool;
2926 struct timeval tv_submit_reply;
2927 char worktime[200] = "";
2928
2929 gettimeofday(&tv_submit_reply, NULL((void*)0));
2930
2931 if (unlikely(!val)(!val)) {
2932 applog(LOG_INFO6, "submit_upstream_work json_rpc_call failed");
2933 if (!pool_tset(pool, &pool->submit_fail)) {
2934 total_ro++;
2935 pool->remotefail_occasions++;
2936 applog(LOG_WARNING4, "Pool %d communication failure, caching submissions", pool->pool_no);
2937 }
2938 goto out;
2939 } else if (pool_tclear(pool, &pool->submit_fail))
2940 applog(LOG_WARNING4, "Pool %d communication resumed, submitting work", pool->pool_no);
2941
2942 res = json_object_get(val, "result");
2943 err = json_object_get(val, "error");
2944
2945 if (!QUIET(opt_quiet || opt_realquiet)) {
2946 if (opt_worktime) {
2947 char workclone[20];
2948 struct tm _tm;
2949 struct tm *tm, tm_getwork, tm_submit_reply;
2950 tm = &_tm;
2951 double getwork_time = tdiff((struct timeval *)&(work->tv_getwork_reply),
2952 (struct timeval *)&(work->tv_getwork));
2953 double getwork_to_work = tdiff((struct timeval *)&(work->tv_work_start),
2954 (struct timeval *)&(work->tv_getwork_reply));
2955 double work_time = tdiff((struct timeval *)&(work->tv_work_found),
2956 (struct timeval *)&(work->tv_work_start));
2957 double work_to_submit = tdiff(ptv_submit,
2958 (struct timeval *)&(work->tv_work_found));
2959 double submit_time = tdiff(&tv_submit_reply, ptv_submit);
2960 int diffplaces = 3;
2961
2962 localtime_r(&(work->tv_getwork.tv_sec), tm);
2963 memcpy(&tm_getwork, tm, sizeof(struct tm));
2964 localtime_r(&(tv_submit_reply.tv_sec), tm);
2965 memcpy(&tm_submit_reply, tm, sizeof(struct tm));
2966
2967 if (work->clone) {
2968 sprintf(workclone, "C:%1.3f",
2969 tdiff((struct timeval *)&(work->tv_cloned),
2970 (struct timeval *)&(work->tv_getwork_reply)));
2971 }
2972 else
2973 strcpy(workclone, "O");
2974
2975 if (work->work_difficulty < 1)
2976 diffplaces = 6;
2977
2978 sprintf(worktime, " <-%08lx.%08lx M:%c D:%1.*f G:%02d:%02d:%02d:%1.3f %s (%1.3f) W:%1.3f (%1.3f) S:%1.3f R:%02d:%02d:%02d",
2979 (unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 32 : 28])),
2980 (unsigned long)swab32(*(uint32_t *)&(work->data[opt_scrypt ? 28 : 24])),
2981 work->getwork_mode, diffplaces, work->work_difficulty,
2982 tm_getwork.tm_hour, tm_getwork.tm_min,
2983 tm_getwork.tm_sec, getwork_time, workclone,
2984 getwork_to_work, work_time, work_to_submit, submit_time,
2985 tm_submit_reply.tm_hour, tm_submit_reply.tm_min,
2986 tm_submit_reply.tm_sec);
2987 }
2988 }
2989
2990 share_result(val, res, err, work, resubmit, worktime);
2991
2992 if (!opt_realquiet)
2993 print_status(thr_id);
2994 if (!want_per_device_stats) {
2995 char logline[256];
2996
2997 get_statline(logline, cgpu)get_statline2(logline, cgpu, 0);
2998 applog(LOG_INFO6, "%s", logline);
2999 }
3000
3001 json_decref(val);
3002
3003 rc = true1;
3004out:
3005 return rc;
3006}
3007
3008/* In balanced mode, the amount of diff1 solutions per pool is monitored as a
3009 * rolling average per 10 minutes and if pools start getting more, it biases
3010 * away from them to distribute work evenly. The share count is reset to the
3011 * rolling average every 10 minutes to not send all work to one pool after it
3012 * has been disabled/out for an extended period. */
3013static struct pool *select_balanced(struct pool *cp)
3014{
3015 int i, lowest = cp->shares;
3016 struct pool *ret = cp;
3017
3018 for (i = 0; i < total_pools; i++) {
3019 struct pool *pool = pools[i];
3020
3021 if (pool->idle || pool->enabled != POOL_ENABLED)
3022 continue;
3023 if (pool->shares < lowest) {
3024 lowest = pool->shares;
3025 ret = pool;
3026 }
3027 }
3028
3029 ret->shares++;
3030 return ret;
3031}
3032
3033static bool_Bool pool_active(struct pool *, bool_Bool pinging);
3034static void pool_died(struct pool *);
3035
3036/* Select any active pool in a rotating fashion when loadbalance is chosen */
3037static inline struct pool *select_pool(bool_Bool lagging)
3038{
3039 static int rotating_pool = 0;
3040 struct pool *pool, *cp;
3041
3042 cp = current_pool();
3043
3044retry:
3045 if (pool_strategy == POOL_BALANCE)
3046 {
3047 pool = select_balanced(cp);
3048 goto have_pool;
3049 }
3050
3051 if (pool_strategy != POOL_LOADBALANCE && (!lagging || opt_fail_only))
3052 pool = cp;
3053 else
3054 pool = NULL((void*)0);
3055
3056 while (!pool) {
3057 if (++rotating_pool >= total_pools)
3058 rotating_pool = 0;
3059 pool = pools[rotating_pool];
3060 if ((!pool->idle && pool->enabled == POOL_ENABLED) || pool == cp)
3061 break;
3062 pool = NULL((void*)0);
3063 }
3064
3065have_pool:
3066 if (cp != pool)
3067 {
3068 if (!pool_active(pool, false0))
3069 {
3070 pool_died(pool);
3071 goto retry;
3072 }
3073 pool_tclear(pool, &pool->idle);
3074 }
3075 return pool;
3076}
3077
3078static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0;
3079
3080static double target_diff(const unsigned char *target)
3081{
3082 double targ = 0;
3083 signed int i;
3084
3085 for (i = 31; i >= 0; --i)
3086 targ = (targ * 0x100) + target[i];
3087
3088 return DIFFEXACTONE / (targ ?: 1);
3089}
3090
3091/*
3092 * Calculate the work share difficulty
3093 */
3094static void calc_diff(struct work *work, int known)
3095{
3096 struct cgminer_pool_stats *pool_stats = &(work->pool->cgminer_pool_stats);
3097 double difficulty;
3098
3099 if (!known) {
3100 work->work_difficulty = target_diff(work->target);
3101 } else
3102 work->work_difficulty = known;
3103 difficulty = work->work_difficulty;
3104
3105 pool_stats->last_diff = difficulty;
3106 suffix_string((uint64_t)difficulty, work->pool->diff, 0);
3107
3108 if (difficulty == pool_stats->min_diff)
3109 pool_stats->min_diff_count++;
3110 else if (difficulty < pool_stats->min_diff || pool_stats->min_diff == 0) {
3111 pool_stats->min_diff = difficulty;
3112 pool_stats->min_diff_count = 1;
3113 }
3114
3115 if (difficulty == pool_stats->max_diff)
3116 pool_stats->max_diff_count++;
3117 else if (difficulty > pool_stats->max_diff) {
3118 pool_stats->max_diff = difficulty;
3119 pool_stats->max_diff_count = 1;
3120 }
3121}
3122
3123static void get_benchmark_work(struct work *work)
3124{
3125 // Use a random work block pulled from a pool
3126 static uint8_t bench_block[] = { CGMINER_BENCHMARK_BLOCK0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0xD8, 0x07, 0x17, 0xC9, 0x13
, 0x6F, 0xDC, 0xBE, 0xDE, 0xB7, 0xB2, 0x14, 0xEF, 0xD1, 0x72,
0x7F, 0xA3, 0x72, 0xB2, 0x5D, 0x88, 0xF0, 0x00, 0x00, 0x05, 0xAA
, 0x00, 0x00, 0x00, 0x00, 0x92, 0x8B, 0x4C, 0x77, 0xF5, 0xB2,
0xE6, 0x56, 0x96, 0x27, 0xE0, 0x66, 0x3C, 0x5B, 0xDD, 0xDC, 0x88
, 0x6A, 0x7D, 0x7C, 0x7B, 0x8C, 0xE4, 0x92, 0x38, 0x92, 0x58,
0x2E, 0x18, 0x4D, 0x95, 0x9E, 0x4E, 0x44, 0xF1, 0x5F, 0x1A, 0x08
, 0xE1, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x86, 0x7E, 0x3A, 0xAF, 0x37, 0x83, 0xAF, 0xA0
, 0xB5, 0x33, 0x2C, 0x28, 0xED, 0xA9, 0x89, 0x3E, 0x0A, 0xB6,
0x46, 0x81, 0xC2, 0x71, 0x4F, 0x34, 0x5A, 0x74, 0x89, 0x0E, 0x2B
, 0x04, 0xB3, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0
, 0xF6, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x55, 0xF1, 0x44,
0x4E, 0x00, 0x00, 0x00, 0x00, 0x79, 0x63, 0x01, 0x00, 0x00, 0x00
, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
3127
3128 size_t bench_size = sizeof(*work);
3129 size_t work_size = sizeof(bench_block);
3130 size_t min_size = (work_size < bench_size ? work_size : bench_size);
3131 memset(work, 0, sizeof(*work));
3132 memcpy(work, &bench_block, min_size);
3133 work->mandatory = true1;
3134 work->pool = pools[0];
3135 gettimeofday(&(work->tv_getwork), NULL((void*)0));
3136 memcpy(&(work->tv_getwork_reply), &(work->tv_getwork), sizeof(struct timeval));
3137 work->getwork_mode = GETWORK_MODE_BENCHMARK'B';
3138 calc_diff(work, 0);
3139}
3140
3141static void wake_gws(void);
3142
3143static void update_last_work(struct work *work)
3144{
3145 if (!work->tmpl)
3146 // Only save GBT jobs, since rollntime isn't coordinated well yet
3147 return;
3148
3149 struct pool *pool = work->pool;
3150 mutex_lock(&pool->last_work_lock);
3151 if (pool->last_work_copy)
3152 free_work(pool->last_work_copy);
3153 pool->last_work_copy = copy_work(work);
3154 pool->last_work_copy->work_restart_id = pool->work_restart_id;
3155 mutex_unlock(&pool->last_work_lock);
3156}
3157
3158static
3159void gbt_req_target(json_t *req)
3160{
3161 json_t *j;
3162 json_t *n;
3163
3164 if (!request_target_str)
3165 return;
3166
3167 j = json_object_get(req, "params");
3168 if (!j)
3169 {
3170 n = json_array();
3171 if (!n)
3172 return;
3173 if (json_object_set_new(req, "params", n))
3174 goto erradd;
3175 j = n;
3176 }
3177
3178 n = json_array_get(j, 0);
3179 if (!n)
3180 {
3181 n = json_object();
3182 if (!n)
3183 return;
3184 if (json_array_append_new(j, n))
3185 goto erradd;
3186 }
3187 j = n;
3188
3189 n = json_string(request_target_str);
3190 if (!n)
3191 return;
3192 if (json_object_set_new(j, "target", n))
3193 goto erradd;
3194
3195 return;
3196
3197erradd:
3198 json_decref(n);
3199}
3200
3201static char *prepare_rpc_req2(struct work *work, enum pool_protocol proto, const char *lpid, bool_Bool probe)
3202{
3203 char *rpc_req;
3204
3205 clean_work(work);
3206 switch (proto) {
3207 case PLP_GETWORK:
3208 work->getwork_mode = GETWORK_MODE_POOL'P';
3209 return strdup(getwork_req);
3210 case PLP_GETBLOCKTEMPLATE:
3211 work->getwork_mode = GETWORK_MODE_GBT'G';
3212 work->tmpl_refcount = malloc(sizeof(*work->tmpl_refcount));
3213 if (!work->tmpl_refcount)
3214 return NULL((void*)0);
3215 work->tmpl = blktmpl_create();
3216 if (!work->tmpl)
3217 goto gbtfail2;
3218 *work->tmpl_refcount = 1;
3219 gbt_capabilities_t caps = blktmpl_addcaps(work->tmpl);
3220 if (!caps)
3221 goto gbtfail;
3222 caps |= GBT_LONGPOLL;
3223 json_t *req = blktmpl_request_jansson(caps, lpid);
3224 if (!req)
3225 goto gbtfail;
3226
3227 if (probe)
3228 gbt_req_target(req);
3229
3230 rpc_req = json_dumps(req, 0);
3231 if (!rpc_req)
3232 goto gbtfail;
3233 json_decref(req);
3234 return rpc_req;
3235 default:
3236 return NULL((void*)0);
3237 }
3238 return NULL((void*)0);
3239
3240gbtfail:
3241 blktmpl_free(work->tmpl);
3242 work->tmpl = NULL((void*)0);
3243gbtfail2:
3244 free(work->tmpl_refcount);
3245 work->tmpl_refcount = NULL((void*)0);
3246 return NULL((void*)0);
3247}
3248
3249#define prepare_rpc_req(work, proto, lpid)prepare_rpc_req2(work, proto, lpid, 0) prepare_rpc_req2(work, proto, lpid, false0)
3250#define prepare_rpc_req_probe(work, proto, lpid)prepare_rpc_req2(work, proto, lpid, 1) prepare_rpc_req2(work, proto, lpid, true1)
3251
3252static const char *pool_protocol_name(enum pool_protocol proto)
3253{
3254 switch (proto) {
3255 case PLP_GETBLOCKTEMPLATE:
3256 return "getblocktemplate";
3257 case PLP_GETWORK:
3258 return "getwork";
3259 default:
3260 return "UNKNOWN";
3261 }
3262}
3263
3264static enum pool_protocol pool_protocol_fallback(enum pool_protocol proto)
3265{
3266 switch (proto) {
3267 case PLP_GETBLOCKTEMPLATE:
3268 if (want_getwork)
3269 return PLP_GETWORK;
3270 default:
3271 return PLP_NONE;
3272 }
3273}
3274
3275static bool_Bool get_upstream_work(struct work *work, CURL *curl)
3276{
3277 struct pool *pool = work->pool;
3278 struct cgminer_pool_stats *pool_stats = &(pool->cgminer_pool_stats);
3279 struct timeval tv_elapsed;
3280 json_t *val = NULL((void*)0);
3281 bool_Bool rc = false0;
3282 char *url;
3283 enum pool_protocol proto;
3284
3285 char *rpc_req;
3286
3287 if (pool->proto == PLP_NONE)
3288 pool->proto = PLP_GETBLOCKTEMPLATE;
3289
3290tryagain:
3291 rpc_req = prepare_rpc_req(work, pool->proto, NULL)prepare_rpc_req2(work, pool->proto, ((void*)0), 0);
3292 work->pool = pool;
3293 if (!rpc_req)
3294 return false0;
3295
3296 applog(LOG_DEBUG7, "DBG: sending %s get RPC call: %s", pool->rpc_url, rpc_req);
3297
3298 url = pool->rpc_url;
3299
3300 gettimeofday(&(work->tv_getwork), NULL((void*)0));
3301
3302 val = json_rpc_call(curl, url, pool->rpc_userpass, rpc_req, false0,
3303 false0, &work->rolltime, pool, false0);
3304 pool_stats->getwork_attempts++;
3305
3306 free(rpc_req);
3307
3308 if (likely(val)(val)) {
3309 rc = work_decode(pool, work, val);
3310 if (unlikely(!rc)(!rc))
3311 applog(LOG_DEBUG7, "Failed to decode work in get_upstream_work");
3312 } else if (PLP_NONE != (proto = pool_protocol_fallback(pool->proto))) {
3313 applog(LOG_WARNING4, "Pool %u failed getblocktemplate request; falling back to getwork protocol", pool->pool_no);
3314 pool->proto = proto;
3315 goto tryagain;
3316 } else
3317 applog(LOG_DEBUG7, "Failed json_rpc_call in get_upstream_work");
3318
3319 gettimeofday(&(work->tv_getwork_reply), NULL((void*)0));
3320 timersub(&(work->tv_getwork_reply), &(work->tv_getwork), &tv_elapsed)do { (&tv_elapsed)->tv_sec = (&(work->tv_getwork_reply
))->tv_sec - (&(work->tv_getwork))->tv_sec; (&
tv_elapsed)->tv_usec = (&(work->tv_getwork_reply))->
tv_usec - (&(work->tv_getwork))->tv_usec; if ((&
tv_elapsed)->tv_usec < 0) { --(&tv_elapsed)->tv_sec
; (&tv_elapsed)->tv_usec += 1000000; } } while (0)
;
3321 pool_stats->getwork_wait_rolling += ((double)tv_elapsed.tv_sec + ((double)tv_elapsed.tv_usec / 1000000)) * 0.63;
3322 pool_stats->getwork_wait_rolling /= 1.63;
3323
3324 timeradd(&tv_elapsed, &(pool_stats->getwork_wait), &(pool_stats->getwork_wait))do { (&(pool_stats->getwork_wait))->tv_sec = (&
tv_elapsed)->tv_sec + (&(pool_stats->getwork_wait))
->tv_sec; (&(pool_stats->getwork_wait))->tv_usec
= (&tv_elapsed)->tv_usec + (&(pool_stats->getwork_wait
))->tv_usec; if ((&(pool_stats->getwork_wait))->
tv_usec >= 1000000) { ++(&(pool_stats->getwork_wait
))->tv_sec; (&(pool_stats->getwork_wait))->tv_usec
-= 1000000; } } while (0)
;
3325 if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_max), >)(((&tv_elapsed)->tv_sec == (&(pool_stats->getwork_wait_max
))->tv_sec) ? ((&tv_elapsed)->tv_usec > (&(pool_stats
->getwork_wait_max))->tv_usec) : ((&tv_elapsed)->
tv_sec > (&(pool_stats->getwork_wait_max))->tv_sec
))
) {
3326 pool_stats->getwork_wait_max.tv_sec = tv_elapsed.tv_sec;
3327 pool_stats->getwork_wait_max.tv_usec = tv_elapsed.tv_usec;
3328 }
3329 if (timercmp(&tv_elapsed, &(pool_stats->getwork_wait_min), <)(((&tv_elapsed)->tv_sec == (&(pool_stats->getwork_wait_min
))->tv_sec) ? ((&tv_elapsed)->tv_usec < (&(pool_stats
->getwork_wait_min))->tv_usec) : ((&tv_elapsed)->
tv_sec < (&(pool_stats->getwork_wait_min))->tv_sec
))
) {
3330 pool_stats->getwork_wait_min.tv_sec = tv_elapsed.tv_sec;
3331 pool_stats->getwork_wait_min.tv_usec = tv_elapsed.tv_usec;
3332 }
3333 pool_stats->getwork_calls++;
3334
3335 work->pool = pool;
3336 work->longpoll = false0;
3337 calc_diff(work, 0);
3338 total_getworks++;
3339 pool->getwork_requested++;
3340
3341 if (rc)
3342 update_last_work(work);
3343
3344 if (likely(val)(val))
3345 json_decref(val);
3346
3347 return rc;
3348}
3349
3350#ifdef HAVE_CURSES1
3351static void disable_curses(void)
3352{
3353 if (curses_active_locked()) {
3354 curses_active = false0;
3355 leaveok(logwin, false0);
3356 leaveok(statuswin, false0);
3357 leaveok(mainwin, false0);
3358 nocbreak();
3359 echo();
3360 delwin(logwin);
3361 delwin(statuswin);
3362 delwin(mainwin);
3363 endwin();
3364#ifdef WIN32
3365 // Move the cursor to after curses output.
3366 HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
3367 CONSOLE_SCREEN_BUFFER_INFO csbi;
3368 COORD coord;
3369
3370 if (GetConsoleScreenBufferInfo(hout, &csbi)) {
3371 coord.X = 0;
3372 coord.Y = csbi.dwSize.Y - 1;
3373 SetConsoleCursorPosition(hout, coord);
3374 }
3375#endif
3376 unlock_curses();
3377 }
3378}
3379#endif
3380
3381static void __kill_work(void)
3382{
3383 struct thr_info *thr;
3384 int i;
3385
3386 if (!successful_connect)
3387 return;
3388
3389 applog(LOG_INFO6, "Received kill message");
3390
3391 shutting_down = true1;
3392
3393 applog(LOG_DEBUG7, "Prompting submit_work thread to finish");
3394 notifier_wake(submit_waiting_notifier);
3395
3396 applog(LOG_DEBUG7, "Killing off watchpool thread");
3397 /* Kill the watchpool thread */
3398 thr = &thr_info[watchpool_thr_id];
3399 thr_info_cancel(thr);
3400
3401 applog(LOG_DEBUG7, "Killing off watchdog thread");
3402 /* Kill the watchdog thread */
3403 thr = &thr_info[watchdog_thr_id];
3404 thr_info_cancel(thr);
3405
3406 applog(LOG_DEBUG7, "Stopping mining threads");
3407 /* Stop the mining threads*/
3408 for (i = 0; i < mining_threads; i++) {
3409 thr = &thr_info[i];
3410 if (thr->cgpu->threads)
3411 thr_info_freeze(thr);
3412 thr->pause = true1;
3413 }
3414
3415 sleep(1);
3416
3417 applog(LOG_DEBUG7, "Killing off mining threads");
3418 /* Kill the mining threads*/
3419 for (i = 0; i < mining_threads; i++) {
3420 thr = &thr_info[i];
3421 if (thr->cgpu->threads)
3422 thr_info_cancel(thr);
3423 }
3424
3425 applog(LOG_DEBUG7, "Killing off stage thread");
3426 /* Stop the others */
3427 thr = &thr_info[stage_thr_id];
3428 thr_info_cancel(thr);
3429
3430 applog(LOG_DEBUG7, "Killing off API thread");
3431 thr = &thr_info[api_thr_id];
3432 thr_info_cancel(thr);
3433}
3434
3435/* This should be the common exit path */
3436void kill_work(void)
3437{
3438 __kill_work();
3439
3440 quit(0, "Shutdown signal received.");
3441}
3442
3443static
3444#ifdef WIN32
3445#ifndef _WIN64
3446const
3447#endif
3448#endif
3449char **initial_args;
3450
3451static void clean_up(void);
3452
3453void app_restart(void)
3454{
3455 applog(LOG_WARNING4, "Attempting to restart %s", packagename);
3456
3457 __kill_work();
3458 clean_up();
3459
3460#if defined(unix1)
3461 if (forkpid > 0) {
3462 kill(forkpid, SIGTERM15);
3463 forkpid = 0;
3464 }
3465#endif
3466
3467 execv(initial_args[0], initial_args);
3468 applog(LOG_WARNING4, "Failed to restart application");
3469}
3470
3471static void sighandler(int __maybe_unused__attribute__((unused)) sig)
3472{
3473 /* Restore signal handlers so we can still quit if kill_work fails */
3474 sigaction(SIGTERM15, &termhandler, NULL((void*)0));
3475 sigaction(SIGINT2, &inthandler, NULL((void*)0));
3476 kill_work();
3477}
3478
3479static void start_longpoll(void);
3480static void stop_longpoll(void);
3481
3482/* Called with pool_lock held. Recruit an extra curl if none are available for
3483 * this pool. */
3484static void recruit_curl(struct pool *pool)
3485{
3486 struct curl_ent *ce = calloc(sizeof(struct curl_ent), 1);
3487
3488 if (unlikely(!ce)(!ce))
3489 quit(1, "Failed to calloc in recruit_curl");
3490
3491 ce->curl = curl_easy_init();
3492 if (unlikely(!ce->curl)(!ce->curl))
3493 quit(1, "Failed to init in recruit_curl");
3494
3495 list_add(&ce->node, &pool->curlring);
3496 pool->curls++;
3497 applog(LOG_DEBUG7, "Recruited curl %d for pool %d", pool->curls, pool->pool_no);
3498}
3499
3500/* Grab an available curl if there is one. If not, then recruit extra curls
3501 * unless we are in a submit_fail situation, or we have opt_delaynet enabled
3502 * and there are already 5 curls in circulation. Limit total number to the
3503 * number of mining threads per pool as well to prevent blasting a pool during
3504 * network delays/outages. */
3505static struct curl_ent *pop_curl_entry3(struct pool *pool, int blocking)
3506{
3507 int curl_limit = opt_delaynet ? 5 : (mining_threads + opt_queue) * 2;
3508 struct curl_ent *ce;
3509
3510 mutex_lock(&pool->pool_lock);
3511retry:
3512 if (!pool->curls)
3513 recruit_curl(pool);
3514 else if (list_empty(&pool->curlring)) {
3515 if (blocking < 2 && pool->curls >= curl_limit && (blocking || pool->curls >= opt_submit_threads)) {
3516 if (!blocking) {
3517 mutex_unlock(&pool->pool_lock);
3518 return NULL((void*)0);
3519 }
3520 pthread_cond_wait(&pool->cr_cond, &pool->pool_lock);
3521 goto retry;
3522 } else
3523 recruit_curl(pool);
3524 }
3525 ce = list_entry(pool->curlring.next, struct curl_ent, node)((struct curl_ent *)((char *)(pool->curlring.next)-(intptr_t
)(&((struct curl_ent *)0)->node)))
;
3526 list_del(&ce->node);
3527 mutex_unlock(&pool->pool_lock);
3528
3529 return ce;
3530}
3531
3532static struct curl_ent *pop_curl_entry2(struct pool *pool, bool_Bool blocking)
3533{
3534 return pop_curl_entry3(pool, blocking ? 1 : 0);
3535}
3536
3537__maybe_unused__attribute__((unused))
3538static struct curl_ent *pop_curl_entry(struct pool *pool)
3539{
3540 return pop_curl_entry3(pool, 1);
3541}
3542
3543static void push_curl_entry(struct curl_ent *ce, struct pool *pool)
3544{
3545 mutex_lock(&pool->pool_lock);
3546 if (!ce || !ce->curl)
3547 quit(1, "Attempted to add NULL in push_curl_entry");
3548 list_add_tail(&ce->node, &pool->curlring);
3549 gettimeofday(&ce->tv, NULL((void*)0));
3550 pthread_cond_broadcast(&pool->cr_cond);
3551 mutex_unlock(&pool->pool_lock);
3552}
3553
3554bool_Bool stale_work(struct work *work, bool_Bool share);
3555
3556static inline bool_Bool should_roll(struct work *work)
3557{
3558 struct timeval now;
3559 time_t expiry;
3560
3561 if (work->pool != current_pool() && pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE)
3562 return false0;
3563
3564 if (stale_work(work, false0))
3565 return false0;
3566
3567 if (work->rolltime > opt_scantime)
3568 expiry = work->rolltime;
3569 else
3570 expiry = opt_scantime;
3571 expiry = expiry * 2 / 3;
3572
3573 /* We shouldn't roll if we're unlikely to get one shares' duration
3574 * work out of doing so */
3575 gettimeofday(&now, NULL((void*)0));
3576 if (now.tv_sec - work->tv_staged.tv_sec > expiry)
3577 return false0;
3578
3579 return true1;
3580}
3581
3582/* Limit rolls to 7000 to not beyond 2 hours in the future where bitcoind will
3583 * reject blocks as invalid. */
3584static inline bool_Bool can_roll(struct work *work)
3585{
3586 if (work->stratum)
3587 return false0;
3588 if (!(work->pool && !work->clone))
3589 return false0;
3590 if (work->tmpl) {
3591 if (stale_work(work, false0))
3592 return false0;
3593 return blkmk_work_left(work->tmpl);
3594 }
3595 return (work->rolltime &&
3596 work->rolls < 7000 && !stale_work(work, false0));
3597}
3598
3599static void roll_work(struct work *work)
3600{
3601 if (work->tmpl) {
3602 if (blkmk_get_data(work->tmpl, work->data, 80, time(NULL((void*)0)), NULL((void*)0), &work->dataid) < 76)
3603 applog(LOG_ERR3, "Failed to get next data from template; spinning wheels!");
3604 swap32yes(work->data, work->data, 80 / 4);
3605 calc_midstate(work);
3606 applog(LOG_DEBUG7, "Successfully rolled extranonce to dataid %u", work->dataid);
3607 } else {
3608
3609 uint32_t *work_ntime;
3610 uint32_t ntime;
3611
3612 work_ntime = (uint32_t *)(work->data + 68);
3613 ntime = be32toh(*work_ntime)(__extension__ ({ register unsigned int __v, __x = (*work_ntime
); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
3614 ntime++;
3615 *work_ntime = htobe32(ntime)(__extension__ ({ register unsigned int __v, __x = (ntime); if
(__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; }))
;
3616
3617 applog(LOG_DEBUG7, "Successfully rolled time header in work");
3618 }
3619
3620 local_work++;
3621 work->rolls++;
3622 work->blk.nonce = 0;
3623
3624 /* This is now a different work item so it needs a different ID for the
3625 * hashtable */
3626 work->id = total_work++;
3627}
3628
3629/* Duplicates any dynamically allocated arrays within the work struct to
3630 * prevent a copied work struct from freeing ram belonging to another struct */
3631void __copy_work(struct work *work, const struct work *base_work)
3632{
3633 int id = work->id;
3634
3635 clean_work(work);
3636 memcpy(work, base_work, sizeof(struct work));
3637 /* Keep the unique new id assigned during make_work to prevent copied
3638 * work from having the same id. */
3639 work->id = id;
3640 if (base_work->job_id)
3641 work->job_id = strdup(base_work->job_id);
3642 if (base_work->nonce1)
3643 work->nonce1 = strdup(base_work->nonce1);
3644 if (base_work->nonce2)
3645 work->nonce2 = strdup(base_work->nonce2);
3646 if (base_work->ntime)
3647 work->ntime = strdup(base_work->ntime);
3648
3649 if (base_work->tmpl) {
3650 struct pool *pool = work->pool;
3651 mutex_lock(&pool->pool_lock);
3652 ++*work->tmpl_refcount;
3653 mutex_unlock(&pool->pool_lock);
3654 }
3655}
3656
3657/* Generates a copy of an existing work struct, creating fresh heap allocations
3658 * for all dynamically allocated arrays within the struct */
3659struct work *copy_work(const struct work *base_work)
3660{
3661 struct work *work = make_work();
3662
3663 __copy_work(work, base_work);
3664
3665 return work;
3666}
3667
3668static struct work *make_clone(struct work *work)
3669{
3670 struct work *work_clone = copy_work(work);
3671
3672 work_clone->clone = true1;
3673 gettimeofday((struct timeval *)&(work_clone->tv_cloned), NULL((void*)0));
3674 work_clone->longpoll = false0;
3675 work_clone->mandatory = false0;
3676 /* Make cloned work appear slightly older to bias towards keeping the
3677 * master work item which can be further rolled */
3678 work_clone->tv_staged.tv_sec -= 1;
3679
3680 return work_clone;
3681}
3682
3683static void stage_work(struct work *work);
3684
3685static bool_Bool clone_available(void)
3686{
3687 struct work *work_clone = NULL((void*)0), *work, *tmp;
3688 bool_Bool cloned = false0;
3689
3690 mutex_lock(stgd_lock);
3691 if (!staged_rollable)
3692 goto out_unlock;
3693
3694 HASH_ITER(hh, staged_work, work, tmp)for((work)=(staged_work),(tmp)=(__typeof(work))((staged_work)
?(staged_work)->hh.next:((void*)0)); work; (work)=(tmp),(tmp
)=(__typeof(work))((tmp)?(tmp)->hh.next:((void*)0)))
{
3695 if (can_roll(work) && should_roll(work)) {
3696 roll_work(work);
3697 work_clone = make_clone(work);
3698 roll_work(work);
3699 applog(LOG_DEBUG7, "Pushing cloned available work to stage thread");
3700 cloned = true1;
3701 break;
3702 }
3703 }
3704
3705out_unlock:
3706 mutex_unlock(stgd_lock);
3707
3708 if (cloned)
3709 stage_work(work_clone);
3710 return cloned;
3711}
3712
3713static void pool_died(struct pool *pool)
3714{
3715 if (!pool_tset(pool, &pool->idle)) {
3716 gettimeofday(&pool->tv_idle, NULL((void*)0));
3717 if (pool == current_pool()) {
3718 applog(LOG_WARNING4, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
3719 switch_pools(NULL((void*)0));
3720 } else
3721 applog(LOG_INFO6, "Pool %d %s failed to return work", pool->pool_no, pool->rpc_url);
3722 }
3723}
3724
3725bool_Bool stale_work(struct work *work, bool_Bool share)
3726{
3727 unsigned work_expiry;
3728 struct pool *pool;
3729 uint32_t block_id;
3730 unsigned getwork_delay;
3731
3732 block_id = ((uint32_t*)work->data)[1];
3733 pool = work->pool;
3734
3735 /* Technically the rolltime should be correct but some pools
3736 * advertise a broken expire= that is lower than a meaningful
3737 * scantime */
3738 if (work->rolltime >= opt_scantime || work->tmpl)
3739 work_expiry = work->rolltime;
3740 else
3741 work_expiry = opt_expiry;
3742
3743 unsigned max_expiry = (have_longpoll ? opt_expiry_lp : opt_expiry);
3744 if (work_expiry > max_expiry)
3745 work_expiry = max_expiry;
3746
3747 if (share) {
3748 /* If the share isn't on this pool's latest block, it's stale */
3749 if (pool->block_id && pool->block_id != block_id)
3750 {
3751 applog(LOG_DEBUG7, "Share stale due to block mismatch (%08lx != %08lx)", (long)block_id, (long)pool->block_id);
3752 return true1;
3753 }
3754
3755 /* If the pool doesn't want old shares, then any found in work before
3756 * the most recent longpoll is stale */
3757 if ((!pool->submit_old) && work->work_restart_id != pool->work_restart_id)
3758 {
3759 applog(LOG_DEBUG7, "Share stale due to mandatory work update (%02x != %02x)", work->work_restart_id, pool->work_restart_id);
3760 return true1;
3761 }
3762 } else {
3763 /* If this work isn't for the latest Bitcoin block, it's stale */
3764 /* But only care about the current pool if failover-only */
3765 if (enabled_pools <= 1 || opt_fail_only) {
3766 if (pool->block_id && block_id != pool->block_id)
3767 {
3768 applog(LOG_DEBUG7, "Work stale due to block mismatch (%08lx != 1 ? %08lx : %08lx)", (long)block_id, (long)pool->block_id, (long)current_block_id);
3769 return true1;
3770 }
3771 } else {
3772 if (block_id != current_block_id)
3773 {
3774 applog(LOG_DEBUG7, "Work stale due to block mismatch (%08lx != 0 ? %08lx : %08lx)", (long)block_id, (long)pool->block_id, (long)current_block_id);
3775 return true1;
3776 }
3777 }
3778
3779 /* If the pool has asked us to restart since this work, it's stale */
3780 if (work->work_restart_id != pool->work_restart_id)
3781 {
3782 applog(LOG_DEBUG7, "Work stale due to work update (%02x != %02x)", work->work_restart_id, pool->work_restart_id);
3783 return true1;
3784 }
3785
3786 if (pool->has_stratum && work->job_id) {
3787 bool_Bool same_job;
3788
3789 if (!pool->stratum_active || !pool->stratum_notify) {
3790 applog(LOG_DEBUG7, "Work stale due to stratum inactive");
3791 return true1;
3792 }
3793
3794 same_job = true1;
3795 mutex_lock(&pool->pool_lock);
3796 if (strcmp(work->job_id, pool->swork.job_id))
3797 same_job = false0;
3798 mutex_unlock(&pool->pool_lock);
3799 if (!same_job) {
3800 applog(LOG_DEBUG7, "Work stale due to stratum job_id mismatch");
3801 return true1;
3802 }
3803 }
3804
3805 /* Factor in the average getwork delay of this pool, rounding it up to
3806 * the nearest second */
3807 getwork_delay = pool->cgminer_pool_stats.getwork_wait_rolling * 5 + 1;
3808 if (unlikely(work_expiry <= getwork_delay + 5)(work_expiry <= getwork_delay + 5))
3809 work_expiry = 5;
3810 else
3811 work_expiry -= getwork_delay;
3812
3813 }
3814
3815 double elapsed_since_staged = difftime(time(NULL((void*)0)), work->tv_staged.tv_sec);
3816 if (elapsed_since_staged > work_expiry) {
3817 applog(LOG_DEBUG7, "%s stale due to expiry (%.0f >= %u)", share?"Share":"Work", elapsed_since_staged, work_expiry);
3818 return true1;
3819 }
3820
3821 /* If the user only wants strict failover, any work from a pool other than
3822 * the current one is always considered stale */
3823 if (opt_fail_only && !share && pool != current_pool() && !work->mandatory &&
3824 pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) {
3825 applog(LOG_DEBUG7, "Work stale due to fail only pool mismatch (pool %u vs %u)", pool->pool_no, current_pool()->pool_no);
3826 return true1;
3827 }
3828
3829 return false0;
3830}
3831
3832static void regen_hash(struct work *work)
3833{
3834 hash_data(work->hash, work->data);
3835}
3836
3837static void check_solve(struct work *work)
3838{
3839 if (opt_scrypt)
3840 scrypt_outputhash(work);
3841 else
3842 regen_hash(work);
3843
3844 work->block = solves_block(work);
3845 if (unlikely(work->block)(work->block)) {
3846 work->pool->solved++;
3847 found_blocks++;
3848 work->mandatory = true1;
3849 applog(LOG_NOTICE5, "Found block for pool %d!", work->pool->pool_no);
3850 }
3851}
3852
3853static void submit_discard_share2(const char *reason, struct work *work)
3854{
3855 sharelog(reason, work);
3856
3857 mutex_lock(&stats_lock);
3858 ++total_stale;
3859 ++(work->pool->stale_shares);
3860 total_diff_stale += work->work_difficulty;
3861 work->pool->diff_stale += work->work_difficulty;
3862 mutex_unlock(&stats_lock);
3863}
3864
3865static void submit_discard_share(struct work *work)
3866{
3867 submit_discard_share2("discard", work);
3868}
3869
3870struct submit_work_state {
3871 struct work *work;
3872 bool_Bool resubmit;
3873 struct curl_ent *ce;
3874 int failures;
3875 time_t staleexpire;
3876 char *s;
3877 struct timeval tv_submit;
3878 struct submit_work_state *next;
3879};
3880
3881static int my_curl_timer_set(__maybe_unused__attribute__((unused)) CURLM *curlm, long timeout_ms, void *userp)
3882{
3883 struct timeval *tvp_timer = userp;
3884 if (timeout_ms == -1)
3885 tvp_timer->tv_sec = -1;
3886 else
3887 timer_set_delay_from_now(tvp_timer, timeout_ms * 1000)do { struct timeval tv_now; gettimeofday(&tv_now, ((void*
)0)); do { struct timeval tv_add = ( (struct timeval){ .tv_sec
= (timeout_ms * 1000) / 1000000, .tv_usec = (timeout_ms * 1000
) % 1000000, } ); do { (tvp_timer)->tv_sec = (&tv_add)
->tv_sec + (&tv_now)->tv_sec; (tvp_timer)->tv_usec
= (&tv_add)->tv_usec + (&tv_now)->tv_usec; if (
(tvp_timer)->tv_usec >= 1000000) { ++(tvp_timer)->tv_sec
; (tvp_timer)->tv_usec -= 1000000; } } while (0); } while(
0); } while(0)
;
3888 return 0;
3889}
3890
3891static void sws_has_ce(struct submit_work_state *sws)
3892{
3893 struct pool *pool = sws->work->pool;
3894 sws->s = submit_upstream_work_request(sws->work);
3895 gettimeofday(&sws->tv_submit, NULL((void*)0));
3896 json_rpc_call_async(sws->ce->curl, pool->rpc_url, pool->rpc_userpass, sws->s, false0, pool, true1, sws);
3897}
3898
3899static struct submit_work_state *begin_submission(struct work *work)
3900{
3901 struct pool *pool;
3902 struct submit_work_state *sws = NULL((void*)0);
3903
3904 pool = work->pool;
3905 sws = malloc(sizeof(*sws));
3906 *sws = (struct submit_work_state){
3907 .work = work,
3908 };
3909
3910 check_solve(work);
3911
3912 if (stale_work(work, true1)) {
3913 work->stale = true1;
3914 if (opt_submit_stale)
3915 applog(LOG_NOTICE5, "Pool %d stale share detected, submitting as user requested", pool->pool_no);
3916 else if (pool->submit_old)
3917 applog(LOG_NOTICE5, "Pool %d stale share detected, submitting as pool requested", pool->pool_no);
3918 else {
3919 applog(LOG_NOTICE5, "Pool %d stale share detected, discarding", pool->pool_no);
3920 submit_discard_share(work);
3921 goto out;
3922 }
3923 sws->staleexpire = time(NULL((void*)0)) + 300;
3924 }
3925
3926 if (work->stratum) {
3927 char *s;
3928
3929 s = malloc(1024);
3930
3931 sws->s = s;
3932 } else {
3933 /* submit solution to bitcoin via JSON-RPC */
3934 sws->ce = pop_curl_entry2(pool, false0);
3935 if (sws->ce) {
3936 sws_has_ce(sws);
3937 } else {
3938 sws->next = pool->sws_waiting_on_curl;
3939 pool->sws_waiting_on_curl = sws;
3940 if (sws->next)
3941 applog(LOG_DEBUG7, "submit_thread queuing submission");
3942 else
3943 applog(LOG_WARNING4, "submit_thread queuing submissions (see --submit-threads)");
3944 }
3945 }
3946
3947 return sws;
3948
3949out:
3950 free(sws);
3951 return NULL((void*)0);
3952}
3953
3954static bool_Bool retry_submission(struct submit_work_state *sws)
3955{
3956 struct work *work = sws->work;
3957 struct pool *pool = work->pool;
3958
3959 sws->resubmit = true1;
3960 if ((!work->stale) && stale_work(work, true1)) {
3961 work->stale = true1;
3962 if (opt_submit_stale)
3963 applog(LOG_NOTICE5, "Pool %d share became stale during submission failure, will retry as user requested", pool->pool_no);
3964 else if (pool->submit_old)
3965 applog(LOG_NOTICE5, "Pool %d share became stale during submission failure, will retry as pool requested", pool->pool_no);
3966 else {
3967 applog(LOG_NOTICE5, "Pool %d share became stale during submission failure, discarding", pool->pool_no);
3968 submit_discard_share(work);
3969 return false0;
3970 }
3971 sws->staleexpire = time(NULL((void*)0)) + 300;
3972 }
3973 if (unlikely((opt_retries >= 0) && (++sws->failures > opt_retries))((opt_retries >= 0) && (++sws->failures > opt_retries
))
) {
3974 applog(LOG_ERR3, "Pool %d failed %d submission retries, discarding", pool->pool_no, opt_retries);
3975 submit_discard_share(work);
3976 return false0;
3977 }
3978 else if (work->stale) {
3979 if (unlikely(opt_retries < 0 && sws->staleexpire <= time(NULL))(opt_retries < 0 && sws->staleexpire <= time
(((void*)0)))
) {
3980 applog(LOG_NOTICE5, "Pool %d stale share failed to submit for 5 minutes, discarding", pool->pool_no);
3981 submit_discard_share(work);
3982 return false0;
3983 }
3984 }
3985
3986 /* pause, then restart work-request loop */
3987 applog(LOG_INFO6, "json_rpc_call failed on submit_work, retrying");
3988
3989 gettimeofday(&sws->tv_submit, NULL((void*)0));
3990 json_rpc_call_async(sws->ce->curl, pool->rpc_url, pool->rpc_userpass, sws->s, false0, pool, true1, sws);
3991
3992 return true1;
3993}
3994
3995static void free_sws(struct submit_work_state *sws)
3996{
3997 free(sws->s);
3998 free_work(sws->work);
3999 free(sws);
4000}
4001
4002static void *submit_work_thread(__maybe_unused__attribute__((unused)) void *userdata)
4003{
4004 int wip = 0;
4005 CURLM *curlm;
4006 struct timeval curlm_timer;
4007 struct submit_work_state *sws, **swsp;
4008 struct submit_work_state *write_sws = NULL((void*)0);
4009 unsigned tsreduce = 0;
4010
4011 pthread_detach(pthread_self());
4012
4013 RenameThread("submit_work");
4014
4015 applog(LOG_DEBUG7, "Creating extra submit work thread");
4016
4017 curlm = curl_multi_init();
4018 curlm_timer.tv_sec = -1;
4019 curl_multi_setopt(curlm, CURLMOPT_TIMERDATA, &curlm_timer)curl_multi_setopt(curlm,CURLMOPT_TIMERDATA,&curlm_timer);
4020 curl_multi_setopt(curlm, CURLMOPT_TIMERFUNCTION, my_curl_timer_set)curl_multi_setopt(curlm,CURLMOPT_TIMERFUNCTION,my_curl_timer_set
)
;
4021
4022 fd_set rfds, wfds, efds;
4023 int maxfd;
4024 struct timeval tv_timeout, tv_now;
4025 int n;
4026 CURLMsg *cm;
4027 FD_ZERO(&rfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&rfds)->fds_bits)[0]) : "memory"
); } while (0)
;
4028 while (1) {
4029 mutex_lock(&submitting_lock);
4030 total_submitting -= tsreduce;
4031 tsreduce = 0;
4032 if (FD_ISSET(submit_waiting_notifier[0], &rfds)((((&rfds)->fds_bits)[((submit_waiting_notifier[0]) / (
8 * (int) sizeof (__fd_mask)))] & ((__fd_mask) 1 <<
((submit_waiting_notifier[0]) % (8 * (int) sizeof (__fd_mask
))))) != 0)
) {
4033 notifier_read(submit_waiting_notifier);
4034 }
4035
4036 // Receive any new submissions
4037 while (!list_empty(&submit_waiting)) {
4038 struct work *work = list_entry(submit_waiting.next, struct work, list)((struct work *)((char *)(submit_waiting.next)-(intptr_t)(&
((struct work *)0)->list)))
;
4039 list_del(&work->list);
4040 if ( (sws = begin_submission(work)) ) {
4041 if (sws->ce)
4042 curl_multi_add_handle(curlm, sws->ce->curl);
4043 else if (sws->s) {
4044 sws->next = write_sws;
4045 write_sws = sws;
4046 }
4047 ++wip;
4048 }
4049 else {
4050 --total_submitting;
4051 free_work(work);
4052 }
4053 }
4054
4055 if (unlikely(shutting_down && !wip)(shutting_down && !wip))
4056 break;
4057 mutex_unlock(&submitting_lock);
4058
4059 FD_ZERO(&rfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&rfds)->fds_bits)[0]) : "memory"
); } while (0)
;
4060 FD_ZERO(&wfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&wfds)->fds_bits)[0]) : "memory"
); } while (0)
;
4061 FD_ZERO(&efds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&efds)->fds_bits)[0]) : "memory"
); } while (0)
;
4062 tv_timeout.tv_sec = -1;
4063
4064 // Setup cURL with select
4065 curl_multi_fdset(curlm, &rfds, &wfds, &efds, &maxfd);
4066 reduce_timeout_to(&tv_timeout, &curlm_timer);
4067
4068 // Setup waiting stratum submissions with select
4069 for (sws = write_sws; sws; sws = sws->next)
4070 {
4071 struct pool *pool = sws->work->pool;
4072 int fd = pool->sock;
4073 if (fd == INVSOCK-1 || (!pool->stratum_auth) || !pool->stratum_notify)
4074 continue;
4075 FD_SET(fd, &wfds)((void) (((&wfds)->fds_bits)[((fd) / (8 * (int) sizeof
(__fd_mask)))] |= ((__fd_mask) 1 << ((fd) % (8 * (int)
sizeof (__fd_mask))))))
;
4076 set_maxfd(&maxfd, fd);
4077 }
4078
4079 // Setup "submit waiting" notifier with select
4080 FD_SET(submit_waiting_notifier[0], &rfds)((void) (((&rfds)->fds_bits)[((submit_waiting_notifier
[0]) / (8 * (int) sizeof (__fd_mask)))] |= ((__fd_mask) 1 <<
((submit_waiting_notifier[0]) % (8 * (int) sizeof (__fd_mask
))))))
;
4081 set_maxfd(&maxfd, submit_waiting_notifier[0]);
4082
4083 // Wait for something interesting to happen :)
4084 gettimeofday(&tv_now, NULL((void*)0));
4085 if (select(maxfd+1, &rfds, &wfds, &efds, select_timeout(&tv_timeout, &tv_now)) < 0) {
4086 FD_ZERO(&rfds)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&rfds)->fds_bits)[0]) : "memory"
); } while (0)
;
4087 continue;
4088 }
4089
4090 // Handle any stratum ready-to-write results
4091 for (swsp = &write_sws; (sws = *swsp); ) {
4092 struct work *work = sws->work;
4093 struct pool *pool = work->pool;
4094 int fd = pool->sock;
4095 bool_Bool sessionid_match;
4096
4097 mutex_lock(&pool->pool_lock);
4098 // NOTE: cgminer only does this check on retries, but BFGMiner does it for even the first/normal submit; therefore, it needs to be such that it always is true on the same connection regardless of session management
4099 // NOTE: Worst case scenario for a false positive: the pool rejects it as H-not-zero
4100 sessionid_match = (!pool->nonce1) || !strcmp(work->nonce1, pool->nonce1);
4101 mutex_unlock(&pool->pool_lock);
4102 if (!sessionid_match)
4103 {
4104 applog(LOG_DEBUG7, "No matching session id for resubmitting stratum share");
4105 submit_discard_share2("disconnect", work);
4106 ++tsreduce;
4107next_write_sws_del:
4108 // Clear the fd from wfds, to avoid potentially blocking on other submissions to the same socket
4109 FD_CLR(fd, &wfds)((void) (((&wfds)->fds_bits)[((fd) / (8 * (int) sizeof
(__fd_mask)))] &= ~((__fd_mask) 1 << ((fd) % (8 * (
int) sizeof (__fd_mask))))))
;
4110 // Delete sws for this submission, since we're done with it
4111 *swsp = sws->next;
4112 free_sws(sws);
4113 --wip;
4114 continue;
4115 }
4116
4117 if (fd == INVSOCK-1 || (!pool->stratum_auth) || (!pool->stratum_notify) || !FD_ISSET(fd, &wfds)((((&wfds)->fds_bits)[((fd) / (8 * (int) sizeof (__fd_mask
)))] & ((__fd_mask) 1 << ((fd) % (8 * (int) sizeof (
__fd_mask))))) != 0)
) {
4118next_write_sws:
4119 // TODO: Check if stale, possibly discard etc
4120 swsp = &sws->next;
4121 continue;
4122 }
4123
4124 char *s = sws->s;
4125 struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
4126 uint32_t nonce;
4127 char *noncehex;
4128
4129 sshare->sshare_time = time(NULL((void*)0));
4130 sshare->work = copy_work(work);
4131 nonce = *((uint32_t *)(work->data + 76));
4132 noncehex = bin2hex((const unsigned char *)&nonce, 4);
4133
4134 mutex_lock(&sshare_lock);
4135 /* Give the stratum share a unique id */
4136 sshare->id = swork_id++;
4137 HASH_ADD_INT(stratum_shares, id, sshare)do { unsigned _ha_bkt; (sshare)->hh.next = ((void*)0); (sshare
)->hh.key = (char*)&((sshare)->id); (sshare)->hh
.keylen = (unsigned)sizeof(int); if (!(stratum_shares)) { stratum_shares
= (sshare); (stratum_shares)->hh.prev = ((void*)0); do { (
stratum_shares)->hh.tbl = (UT_hash_table*)malloc(sizeof(UT_hash_table
)); if (!((stratum_shares)->hh.tbl)) { exit(-1); } memset(
(stratum_shares)->hh.tbl, 0, sizeof(UT_hash_table)); (stratum_shares
)->hh.tbl->tail = &((stratum_shares)->hh); (stratum_shares
)->hh.tbl->num_buckets = 32; (stratum_shares)->hh.tbl
->log2_num_buckets = 5; (stratum_shares)->hh.tbl->hho
= (char*)(&(stratum_shares)->hh) - (char*)(stratum_shares
); (stratum_shares)->hh.tbl->buckets = (UT_hash_bucket*
)malloc(32*sizeof(struct UT_hash_bucket)); if (! (stratum_shares
)->hh.tbl->buckets) { exit(-1); } memset((stratum_shares
)->hh.tbl->buckets, 0, 32*sizeof(struct UT_hash_bucket)
); ; (stratum_shares)->hh.tbl->signature = 0xa0111fe1; }
while(0); } else { (stratum_shares)->hh.tbl->tail->
next = (sshare); (sshare)->hh.prev = ((void*)(((char*)((stratum_shares
)->hh.tbl->tail)) - (((stratum_shares)->hh.tbl)->
hho))); (stratum_shares)->hh.tbl->tail = &((sshare)
->hh); } (stratum_shares)->hh.tbl->num_items++; (sshare
)->hh.tbl = (stratum_shares)->hh.tbl; do { unsigned _hj_i
,_hj_j,_hj_k; char *_hj_key=(char*)(&((sshare)->id)); (
sshare)->hh.hashv = 0xfeedbeef; _hj_i = _hj_j = 0x9e3779b9
; _hj_k = (unsigned)sizeof(int); while (_hj_k >= 12) { _hj_i
+= (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) + ( (unsigned
)_hj_key[2] << 16 ) + ( (unsigned)_hj_key[3] << 24
) ); _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8
) + ( (unsigned)_hj_key[6] << 16 ) + ( (unsigned)_hj_key
[7] << 24 ) ); (sshare)->hh.hashv += (_hj_key[8] + (
(unsigned)_hj_key[9] << 8 ) + ( (unsigned)_hj_key[10] <<
16 ) + ( (unsigned)_hj_key[11] << 24 ) ); do { _hj_i -=
_hj_j; _hj_i -= (sshare)->hh.hashv; _hj_i ^= ( (sshare)->
hh.hashv >> 13 ); _hj_j -= (sshare)->hh.hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 8 ); (sshare)->hh.hashv
-= _hj_i; (sshare)->hh.hashv -= _hj_j; (sshare)->hh.hashv
^= ( _hj_j >> 13 ); _hj_i -= _hj_j; _hj_i -= (sshare)->
hh.hashv; _hj_i ^= ( (sshare)->hh.hashv >> 12 ); _hj_j
-= (sshare)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
16 ); (sshare)->hh.hashv -= _hj_i; (sshare)->hh.hashv -=
_hj_j; (sshare)->hh.hashv ^= ( _hj_j >> 5 ); _hj_i -=
_hj_j; _hj_i -= (sshare)->hh.hashv; _hj_i ^= ( (sshare)->
hh.hashv >> 3 ); _hj_j -= (sshare)->hh.hashv; _hj_j -=
_hj_i; _hj_j ^= ( _hj_i << 10 ); (sshare)->hh.hashv
-= _hj_i; (sshare)->hh.hashv -= _hj_j; (sshare)->hh.hashv
^= ( _hj_j >> 15 ); } while (0); _hj_key += 12; _hj_k -=
12; } (sshare)->hh.hashv += sizeof(int); switch ( _hj_k )
{ case 11: (sshare)->hh.hashv += ( (unsigned)_hj_key[10] <<
24 ); case 10: (sshare)->hh.hashv += ( (unsigned)_hj_key[
9] << 16 ); case 9: (sshare)->hh.hashv += ( (unsigned
)_hj_key[8] << 8 ); case 8: _hj_j += ( (unsigned)_hj_key
[7] << 24 ); case 7: _hj_j += ( (unsigned)_hj_key[6] <<
16 ); case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); case
5: _hj_j += _hj_key[4]; case 4: _hj_i += ( (unsigned)_hj_key
[3] << 24 ); case 3: _hj_i += ( (unsigned)_hj_key[2] <<
16 ); case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); case
1: _hj_i += _hj_key[0]; } do { _hj_i -= _hj_j; _hj_i -= (sshare
)->hh.hashv; _hj_i ^= ( (sshare)->hh.hashv >> 13 )
; _hj_j -= (sshare)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i
<< 8 ); (sshare)->hh.hashv -= _hj_i; (sshare)->hh
.hashv -= _hj_j; (sshare)->hh.hashv ^= ( _hj_j >> 13
); _hj_i -= _hj_j; _hj_i -= (sshare)->hh.hashv; _hj_i ^= (
(sshare)->hh.hashv >> 12 ); _hj_j -= (sshare)->hh
.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i << 16 ); (sshare
)->hh.hashv -= _hj_i; (sshare)->hh.hashv -= _hj_j; (sshare
)->hh.hashv ^= ( _hj_j >> 5 ); _hj_i -= _hj_j; _hj_i
-= (sshare)->hh.hashv; _hj_i ^= ( (sshare)->hh.hashv >>
3 ); _hj_j -= (sshare)->hh.hashv; _hj_j -= _hj_i; _hj_j ^=
( _hj_i << 10 ); (sshare)->hh.hashv -= _hj_i; (sshare
)->hh.hashv -= _hj_j; (sshare)->hh.hashv ^= ( _hj_j >>
15 ); } while (0); _ha_bkt = (sshare)->hh.hashv & ((stratum_shares
)->hh.tbl->num_buckets-1); } while(0); do { (stratum_shares
)->hh.tbl->buckets[_ha_bkt].count++; (&(sshare)->
hh)->hh_next = (stratum_shares)->hh.tbl->buckets[_ha_bkt
].hh_head; (&(sshare)->hh)->hh_prev = ((void*)0); if
((stratum_shares)->hh.tbl->buckets[_ha_bkt].hh_head) {
((stratum_shares)->hh.tbl->buckets[_ha_bkt]).hh_head->
hh_prev = (&(sshare)->hh); } ((stratum_shares)->hh.
tbl->buckets[_ha_bkt]).hh_head=&(sshare)->hh; if ((
stratum_shares)->hh.tbl->buckets[_ha_bkt].count >= (
((stratum_shares)->hh.tbl->buckets[_ha_bkt].expand_mult
+1) * 10) && (&(sshare)->hh)->tbl->noexpand
!= 1) { do { unsigned _he_bkt; unsigned _he_bkt_i; struct UT_hash_handle
*_he_thh, *_he_hh_nxt; UT_hash_bucket *_he_new_buckets, *_he_newbkt
; _he_new_buckets = (UT_hash_bucket*)malloc(2 * (&(sshare
)->hh)->tbl->num_buckets * sizeof(struct UT_hash_bucket
)); if (!_he_new_buckets) { exit(-1); } memset(_he_new_buckets
, 0, 2 * (&(sshare)->hh)->tbl->num_buckets * sizeof
(struct UT_hash_bucket)); (&(sshare)->hh)->tbl->
ideal_chain_maxlen = ((&(sshare)->hh)->tbl->num_items
>> ((&(sshare)->hh)->tbl->log2_num_buckets
+1)) + (((&(sshare)->hh)->tbl->num_items & (
((&(sshare)->hh)->tbl->num_buckets*2)-1)) ? 1 : 0
); (&(sshare)->hh)->tbl->nonideal_items = 0; for
(_he_bkt_i = 0; _he_bkt_i < (&(sshare)->hh)->tbl
->num_buckets; _he_bkt_i++) { _he_thh = (&(sshare)->
hh)->tbl->buckets[ _he_bkt_i ].hh_head; while (_he_thh)
{ _he_hh_nxt = _he_thh->hh_next; do { _he_bkt = ((_he_thh
->hashv) & (((&(sshare)->hh)->tbl->num_buckets
*2) - 1)); } while(0); _he_newbkt = &(_he_new_buckets[ _he_bkt
]); if (++(_he_newbkt->count) > (&(sshare)->hh)
->tbl->ideal_chain_maxlen) { (&(sshare)->hh)->
tbl->nonideal_items++; _he_newbkt->expand_mult = _he_newbkt
->count / (&(sshare)->hh)->tbl->ideal_chain_maxlen
; } _he_thh->hh_prev = ((void*)0); _he_thh->hh_next = _he_newbkt
->hh_head; if (_he_newbkt->hh_head) _he_newbkt->hh_head
->hh_prev = _he_thh; _he_newbkt->hh_head = _he_thh; _he_thh
= _he_hh_nxt; } } free((&(sshare)->hh)->tbl->buckets
); (&(sshare)->hh)->tbl->num_buckets *= 2; (&
(sshare)->hh)->tbl->log2_num_buckets++; (&(sshare
)->hh)->tbl->buckets = _he_new_buckets; (&(sshare
)->hh)->tbl->ineff_expands = ((&(sshare)->hh)
->tbl->nonideal_items > ((&(sshare)->hh)->
tbl->num_items >> 1)) ? ((&(sshare)->hh)->
tbl->ineff_expands+1) : 0; if ((&(sshare)->hh)->
tbl->ineff_expands > 1) { (&(sshare)->hh)->tbl
->noexpand=1; ; } ; } while(0); } } while(0); ; ; ; } while
(0)
;
4138 sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
4139 pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, sshare->id);
4140 mutex_unlock(&sshare_lock);
4141
4142 free(noncehex);
4143
4144 applog(LOG_DEBUG7, "DBG: sending %s submit RPC call: %s", pool->stratum_url, s);
4145
4146 if (likely(stratum_send(pool, s, strlen(s)))(stratum_send(pool, s, strlen(s)))) {
4147 if (pool_tclear(pool, &pool->submit_fail))
4148 applog(LOG_WARNING4, "Pool %d communication resumed, submitting work", pool->pool_no);
4149 applog(LOG_DEBUG7, "Successfully submitted, adding to stratum_shares db");
4150 goto next_write_sws_del;
4151 } else if (!pool_tset(pool, &pool->submit_fail)) {
4152 // Undo stuff
4153 mutex_lock(&sshare_lock);
4154 HASH_DEL(stratum_shares, sshare)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((sshare)->hh.prev == ((void*)0)) && ((sshare)->
hh.next == ((void*)0)) ) { free((stratum_shares)->hh.tbl->
buckets); ; free((stratum_shares)->hh.tbl); stratum_shares
= ((void*)0); } else { _hd_hh_del = &((sshare)->hh); if
((sshare) == ((void*)(((char*)((stratum_shares)->hh.tbl->
tail)) - (((stratum_shares)->hh.tbl)->hho)))) { (stratum_shares
)->hh.tbl->tail = (UT_hash_handle*)((char*)((sshare)->
hh.prev) + (stratum_shares)->hh.tbl->hho); } if ((sshare
)->hh.prev) { ((UT_hash_handle*)((char*)((sshare)->hh.prev
) + (stratum_shares)->hh.tbl->hho))->next = (sshare)
->hh.next; } else { do { (stratum_shares) = (__typeof(stratum_shares
))((sshare)->hh.next); } while(0); } if (_hd_hh_del->next
) { ((UT_hash_handle*)((char*)_hd_hh_del->next + (stratum_shares
)->hh.tbl->hho))->prev = _hd_hh_del->prev; } do {
_hd_bkt = ((_hd_hh_del->hashv) & (((stratum_shares)->
hh.tbl->num_buckets) - 1)); } while(0); ((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).count--; if (((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del) { ((stratum_shares
)->hh.tbl->buckets[_hd_bkt]).hh_head = _hd_hh_del->hh_next
; } if (_hd_hh_del->hh_prev) { _hd_hh_del->hh_prev->
hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del->hh_next
) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del->hh_prev
; }; (stratum_shares)->hh.tbl->num_items--; } ; } while
(0)
;
4155 mutex_unlock(&sshare_lock);
4156 free_work(sshare->work);
4157 free(sshare);
4158
4159 applog(LOG_WARNING4, "Pool %d stratum share submission failure", pool->pool_no);
4160 total_ro++;
4161 pool->remotefail_occasions++;
4162 goto next_write_sws;
4163 }
4164 }
4165
4166 // Handle any cURL activities
4167 curl_multi_perform(curlm, &n);
4168 while( (cm = curl_multi_info_read(curlm, &n)) ) {
4169 if (cm->msg == CURLMSG_DONE)
4170 {
4171 bool_Bool finished;
4172 json_t *val = json_rpc_call_completed(cm->easy_handle, cm->data.result, false0, NULL((void*)0), &sws);
4173 curl_multi_remove_handle(curlm, cm->easy_handle);
4174 finished = submit_upstream_work_completed(sws->work, sws->resubmit, &sws->tv_submit, val);
4175 if (!finished) {
4176 if (retry_submission(sws))
4177 curl_multi_add_handle(curlm, sws->ce->curl);
4178 else
4179 finished = true1;
4180 }
4181
4182 if (finished) {
4183 --wip;
4184 ++tsreduce;
4185 struct pool *pool = sws->work->pool;
4186 if (pool->sws_waiting_on_curl) {
4187 pool->sws_waiting_on_curl->ce = sws->ce;
4188 sws_has_ce(pool->sws_waiting_on_curl);
4189 pool->sws_waiting_on_curl = pool->sws_waiting_on_curl->next;
4190 curl_multi_add_handle(curlm, sws->ce->curl);
4191 } else {
4192 push_curl_entry(sws->ce, sws->work->pool);
4193 }
4194 free_sws(sws);
4195 }
4196 }
4197 }
4198 }
4199 assert(!write_sws)((!write_sws) ? (void) (0) : __assert_fail ("!write_sws", "miner.c"
, 4199, __PRETTY_FUNCTION__))
;
4200 mutex_unlock(&submitting_lock);
4201
4202 curl_multi_cleanup(curlm);
4203
4204 applog(LOG_DEBUG7, "submit_work thread exiting");
4205
4206 return NULL((void*)0);
4207}
4208
4209/* Find the pool that currently has the highest priority */
4210static struct pool *priority_pool(int choice)
4211{
4212 struct pool *ret = NULL((void*)0);
4213 int i;
4214
4215 for (i = 0; i < total_pools; i++) {
4216 struct pool *pool = pools[i];
4217
4218 if (pool->prio == choice) {
4219 ret = pool;
4220 break;
4221 }
4222 }
4223
4224 if (unlikely(!ret)(!ret)) {
4225 applog(LOG_ERR3, "WTF No pool %d found!", choice);
4226 return pools[choice];
4227 }
4228 return ret;
4229}
4230
4231int prioritize_pools(char *param, int *pid)
4232{
4233 char *ptr, *next;
4234 int i, pr, prio = 0;
4235
4236 if (total_pools == 0) {
4237 return MSG_NOPOOL;
4238 }
4239
4240 if (param == NULL((void*)0) || *param == '\0') {
4241 return MSG_MISPID;
4242 }
4243
4244 bool_Bool pools_changed[total_pools];
4245 int new_prio[total_pools];
4246 for (i = 0; i < total_pools; ++i)
4247 pools_changed[i] = false0;
4248
4249 next = param;
4250 while (next && *next) {
4251 ptr = next;
4252 next = strchr(ptr, ',');
4253 if (next)
4254 *(next++) = '\0';
4255
4256 i = atoi(ptr);
4257 if (i < 0 || i >= total_pools) {
4258 *pid = i;
4259 return MSG_INVPID;
4260 }
4261
4262 if (pools_changed[i]) {
4263 *pid = i;
4264 return MSG_DUPPID;
4265 }
4266
4267 pools_changed[i] = true1;
4268 new_prio[i] = prio++;
4269 }
4270
4271 // Only change them if no errors
4272 for (i = 0; i < total_pools; i++) {
4273 if (pools_changed[i])
4274 pools[i]->prio = new_prio[i];
4275 }
4276
4277 // In priority order, cycle through the unchanged pools and append them
4278 for (pr = 0; pr < total_pools; pr++)
4279 for (i = 0; i < total_pools; i++) {
4280 if (!pools_changed[i] && pools[i]->prio == pr) {
4281 pools[i]->prio = prio++;
4282 pools_changed[i] = true1;
4283 break;
4284 }
4285 }
4286
4287 if (current_pool()->prio)
4288 switch_pools(NULL((void*)0));
4289
4290 return MSG_POOLPRIO;
4291}
4292
4293void validate_pool_priorities(void)
4294{
4295 // TODO: this should probably do some sort of logging
4296 int i, j;
4297 bool_Bool used[total_pools];
4298 bool_Bool valid[total_pools];
4299
4300 for (i = 0; i < total_pools; i++)
1
Loop condition is true. Entering loop body
2
Loop condition is false. Execution continues on line 4303
4301 used[i] = valid[i] = false0;
4302
4303 for (i = 0; i < total_pools; i++) {
3
Loop condition is true. Entering loop body
5
Loop condition is false. Execution continues on line 4312
4304 if (pools[i]->prio >=0 && pools[i]->prio < total_pools) {
4
Taking false branch
4305 if (!used[pools[i]->prio]) {
4306 valid[i] = true1;
4307 used[pools[i]->prio] = true1;
4308 }
4309 }
4310 }
4311
4312 for (i = 0; i < total_pools; i++) {
6
Loop condition is true. Entering loop body
11
Loop condition is true. Entering loop body
4313 if (!valid[i]) {
7
Taking true branch
12
Branch condition evaluates to a garbage value
4314 for (j = 0; j < total_pools; j++) {
8
Loop condition is true. Entering loop body
4315 if (!used[j]) {
9
Taking true branch
4316 applog(LOG_WARNING4, "Pool %d priority changed from %d to %d", i, pools[i]->prio, j);
4317 pools[i]->prio = j;
4318 used[j] = true1;
4319 break;
10
Execution continues on line 4312
4320 }
4321 }
4322 }
4323 }
4324}
4325
4326void switch_pools(struct pool *selected)
4327{
4328 struct pool *pool, *last_pool;
4329 int i, pool_no, next_pool;
4330
4331 mutex_lock(&control_lock);
4332 last_pool = currentpool;
4333 pool_no = currentpool->pool_no;
4334
4335 /* Switch selected to pool number 0 and move the rest down */
4336 if (selected) {
4337 if (selected->prio != 0) {
4338 for (i = 0; i < total_pools; i++) {
4339 pool = pools[i];
4340 if (pool->prio < selected->prio)
4341 pool->prio++;
4342 }
4343 selected->prio = 0;
4344 }
4345 }
4346
4347 switch (pool_strategy) {
4348 /* Both of these set to the master pool */
4349 case POOL_BALANCE:
4350 case POOL_FAILOVER:
4351 case POOL_LOADBALANCE:
4352 for (i = 0; i < total_pools; i++) {
4353 pool = priority_pool(i);
4354 if (!pool->idle && pool->enabled == POOL_ENABLED) {
4355 pool_no = pool->pool_no;
4356 break;
4357 }
4358 }
4359 break;
4360 /* Both of these simply increment and cycle */
4361 case POOL_ROUNDROBIN:
4362 case POOL_ROTATE:
4363 if (selected && !selected->idle) {
4364 pool_no = selected->pool_no;
4365 break;
4366 }
4367 next_pool = pool_no;
4368 /* Select the next alive pool */
4369 for (i = 1; i < total_pools; i++) {
4370 next_pool++;
4371 if (next_pool >= total_pools)
4372 next_pool = 0;
4373 pool = pools[next_pool];
4374 if (!pool->idle && pool->enabled == POOL_ENABLED) {
4375 pool_no = next_pool;
4376 break;
4377 }
4378 }
4379 break;
4380 default:
4381 break;
4382 }
4383
4384 currentpool = pools[pool_no];
4385 pool = currentpool;
4386 mutex_unlock(&control_lock);
4387
4388 /* Set the lagging flag to avoid pool not providing work fast enough
4389 * messages in failover only mode since we have to get all fresh work
4390 * as in restart_threads */
4391 if (opt_fail_only)
4392 pool_tset(pool, &pool->lagging);
4393
4394 if (pool != last_pool)
4395 {
4396 pool->block_id = 0;
4397 if (pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) {
4398 applog(LOG_WARNING4, "Switching to pool %d %s", pool->pool_no, pool->rpc_url);
4399 }
4400 }
4401
4402 mutex_lock(&lp_lock);
4403 pthread_cond_broadcast(&lp_cond);
4404 mutex_unlock(&lp_lock);
4405
4406}
4407
4408static void discard_work(struct work *work)
4409{
4410 if (!work->clone && !work->rolls && !work->mined) {
4411 if (work->pool)
4412 work->pool->discarded_work++;
4413 total_discarded++;
4414 applog(LOG_DEBUG7, "Discarded work");
4415 } else
4416 applog(LOG_DEBUG7, "Discarded cloned or rolled work");
4417 free_work(work);
4418}
4419
4420static void wake_gws(void)
4421{
4422 mutex_lock(stgd_lock);
4423 pthread_cond_signal(&gws_cond);
4424 mutex_unlock(stgd_lock);
4425}
4426
4427static void discard_stale(void)
4428{
4429 struct work *work, *tmp;
4430 int stale = 0;
4431
4432 mutex_lock(stgd_lock);
4433 HASH_ITER(hh, staged_work, work, tmp)for((work)=(staged_work),(tmp)=(__typeof(work))((staged_work)
?(staged_work)->hh.next:((void*)0)); work; (work)=(tmp),(tmp
)=(__typeof(work))((tmp)?(tmp)->hh.next:((void*)0)))
{
4434 if (stale_work(work, false0)) {
4435 HASH_DEL(staged_work, work)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((work)->hh.prev == ((void*)0)) && ((work)->hh
.next == ((void*)0)) ) { free((staged_work)->hh.tbl->buckets
); ; free((staged_work)->hh.tbl); staged_work = ((void*)0)
; } else { _hd_hh_del = &((work)->hh); if ((work) == (
(void*)(((char*)((staged_work)->hh.tbl->tail)) - (((staged_work
)->hh.tbl)->hho)))) { (staged_work)->hh.tbl->tail
= (UT_hash_handle*)((char*)((work)->hh.prev) + (staged_work
)->hh.tbl->hho); } if ((work)->hh.prev) { ((UT_hash_handle
*)((char*)((work)->hh.prev) + (staged_work)->hh.tbl->
hho))->next = (work)->hh.next; } else { do { (staged_work
) = (__typeof(staged_work))((work)->hh.next); } while(0); }
if (_hd_hh_del->next) { ((UT_hash_handle*)((char*)_hd_hh_del
->next + (staged_work)->hh.tbl->hho))->prev = _hd_hh_del
->prev; } do { _hd_bkt = ((_hd_hh_del->hashv) & (((
staged_work)->hh.tbl->num_buckets) - 1)); } while(0); (
(staged_work)->hh.tbl->buckets[_hd_bkt]).count--; if ((
(staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del
) { ((staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head =
_hd_hh_del->hh_next; } if (_hd_hh_del->hh_prev) { _hd_hh_del
->hh_prev->hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del
->hh_next) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del
->hh_prev; }; (staged_work)->hh.tbl->num_items--; } ;
} while (0)
;
4436 discard_work(work);
4437 stale++;
4438 }
4439 }
4440 pthread_cond_signal(&gws_cond);
4441 mutex_unlock(stgd_lock);
4442
4443 if (stale)
4444 applog(LOG_DEBUG7, "Discarded %d stales that didn't match current hash", stale);
4445}
4446
4447bool_Bool stale_work_future(struct work *work, bool_Bool share, unsigned long ustime)
4448{
4449 bool_Bool rv;
4450 struct timeval tv, orig;
4451 ldiv_t d;
4452
4453 d = ldiv(ustime, 1000000);
4454 tv = (struct timeval){
4455 .tv_sec = d.quot,
4456 .tv_usec = d.rem,
4457 };
4458 orig = work->tv_staged;
4459 timersub(&orig, &tv, &work->tv_staged)do { (&work->tv_staged)->tv_sec = (&orig)->tv_sec
- (&tv)->tv_sec; (&work->tv_staged)->tv_usec
= (&orig)->tv_usec - (&tv)->tv_usec; if ((&
work->tv_staged)->tv_usec < 0) { --(&work->tv_staged
)->tv_sec; (&work->tv_staged)->tv_usec += 1000000
; } } while (0)
;
4460 rv = stale_work(work, share);
4461 work->tv_staged = orig;
4462
4463 return rv;
4464}
4465
4466static void restart_threads(void)
4467{
4468 struct pool *cp = current_pool();
4469 int i;
4470 struct thr_info *thr;
4471
4472 /* Artificially set the lagging flag to avoid pool not providing work
4473 * fast enough messages after every long poll */
4474 pool_tset(cp, &cp->lagging);
4475
4476 /* Discard staged work that is now stale */
4477 discard_stale();
4478
4479 for (i = 0; i < mining_threads; i++)
4480 {
4481 thr = &thr_info[i];
4482 thr->work_restart = true1;
4483 }
4484
4485 for (i = 0; i < mining_threads; i++)
4486 {
4487 thr = &thr_info[i];
4488 notifier_wake(thr->work_restart_notifier);
4489 }
4490}
4491
4492static char *blkhashstr(unsigned char *hash)
4493{
4494 unsigned char hash_swap[32];
4495 swap256(hash_swap, hash);
4496 swap32tole(hash_swap, hash_swap, 32 / 4)((hash_swap == hash_swap) ? (void)0 : memmove(hash_swap, hash_swap
, 32 / 4))
;
4497 return bin2hex(hash_swap, 32);
4498}
4499
4500static void set_curblock(char *hexstr, unsigned char *hash)
4501{
4502 unsigned char hash_swap[32];
4503 char *old_hash;
4504
4505 current_block_id = ((uint32_t*)hash)[0];
4506 strcpy(current_block, hexstr);
4507 swap256(hash_swap, hash);
4508 swap32tole(hash_swap, hash_swap, 32 / 4)((hash_swap == hash_swap) ? (void)0 : memmove(hash_swap, hash_swap
, 32 / 4))
;
4509
4510 /* Don't free current_hash directly to avoid dereferencing when read
4511 * elsewhere - and update block_timeval inside the same lock */
4512 mutex_lock(&ch_lock);
4513 gettimeofday(&block_timeval, NULL((void*)0));
4514 __update_block_title(hash_swap);
4515 old_hash = current_fullhash;
4516 current_fullhash = bin2hex(hash_swap, 32);
4517 free(old_hash);
4518 mutex_unlock(&ch_lock);
4519
4520 get_timestamp(blocktime, &block_timeval);
4521
4522 applog(LOG_INFO6, "New block: %s diff %s (%s)", current_hash, block_diff, net_hashrate);
4523}
4524
4525/* Search to see if this string is from a block that has been seen before */
4526static bool_Bool block_exists(char *hexstr)
4527{
4528 struct block *s;
4529
4530 rd_lock(&blk_lock);
4531 HASH_FIND_STR(blocks, hexstr, s)do { unsigned _hf_bkt,_hf_hashv; s=((void*)0); if (blocks) { do
{ unsigned _hj_i,_hj_j,_hj_k; char *_hj_key=(char*)(hexstr);
_hf_hashv = 0xfeedbeef; _hj_i = _hj_j = 0x9e3779b9; _hj_k = (
unsigned)strlen(hexstr); while (_hj_k >= 12) { _hj_i += (_hj_key
[0] + ( (unsigned)_hj_key[1] << 8 ) + ( (unsigned)_hj_key
[2] << 16 ) + ( (unsigned)_hj_key[3] << 24 ) ); _hj_j
+= (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) + ( (unsigned
)_hj_key[6] << 16 ) + ( (unsigned)_hj_key[7] << 24
) ); _hf_hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] <<
8 ) + ( (unsigned)_hj_key[10] << 16 ) + ( (unsigned)_hj_key
[11] << 24 ) ); do { _hj_i -= _hj_j; _hj_i -= _hf_hashv
; _hj_i ^= ( _hf_hashv >> 13 ); _hj_j -= _hf_hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 8 ); _hf_hashv -= _hj_i;
_hf_hashv -= _hj_j; _hf_hashv ^= ( _hj_j >> 13 ); _hj_i
-= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv >> 12
); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
16 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv ^= (
_hj_j >> 5 ); _hj_i -= _hj_j; _hj_i -= _hf_hashv; _hj_i
^= ( _hf_hashv >> 3 ); _hj_j -= _hf_hashv; _hj_j -= _hj_i
; _hj_j ^= ( _hj_i << 10 ); _hf_hashv -= _hj_i; _hf_hashv
-= _hj_j; _hf_hashv ^= ( _hj_j >> 15 ); } while (0); _hj_key
+= 12; _hj_k -= 12; } _hf_hashv += strlen(hexstr); switch ( _hj_k
) { case 11: _hf_hashv += ( (unsigned)_hj_key[10] << 24
); case 10: _hf_hashv += ( (unsigned)_hj_key[9] << 16 )
; case 9: _hf_hashv += ( (unsigned)_hj_key[8] << 8 ); case
8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); case 7: _hj_j
+= ( (unsigned)_hj_key[6] << 16 ); case 6: _hj_j += ( (
unsigned)_hj_key[5] << 8 ); case 5: _hj_j += _hj_key[4]
; case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); case
3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); case 2: _hj_i
+= ( (unsigned)_hj_key[1] << 8 ); case 1: _hj_i += _hj_key
[0]; } do { _hj_i -= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv
>> 13 ); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= (
_hj_i << 8 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv
^= ( _hj_j >> 13 ); _hj_i -= _hj_j; _hj_i -= _hf_hashv
; _hj_i ^= ( _hf_hashv >> 12 ); _hj_j -= _hf_hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 16 ); _hf_hashv -= _hj_i
; _hf_hashv -= _hj_j; _hf_hashv ^= ( _hj_j >> 5 ); _hj_i
-= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv >> 3
); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
10 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv ^= (
_hj_j >> 15 ); } while (0); _hf_bkt = _hf_hashv & (
(blocks)->hh.tbl->num_buckets-1); } while(0); if ((1)) {
do { if ((blocks)->hh.tbl->buckets[ _hf_bkt ].hh_head)
do { (s) = (__typeof(s))(((void*)(((char*)((blocks)->hh.tbl
->buckets[ _hf_bkt ].hh_head)) - (((blocks)->hh.tbl)->
hho)))); } while(0); else s=((void*)0); while (s) { if ((s)->
hh.keylen == strlen(hexstr)) { if ((memcmp((s)->hh.key,hexstr
,strlen(hexstr))) == 0) break; } if ((s)->hh.hh_next) do {
(s) = (__typeof(s))(((void*)(((char*)((s)->hh.hh_next)) -
(((blocks)->hh.tbl)->hho)))); } while(0); else s = ((void
*)0); } } while(0); } } } while (0)
;
4532 rd_unlock(&blk_lock);
4533 if (s)
4534 return true1;
4535 return false0;
4536}
4537
4538/* Tests if this work is from a block that has been seen before */
4539static inline bool_Bool from_existing_block(struct work *work)
4540{
4541 char *hexstr = bin2hex(work->data + 8, 18);
4542 bool_Bool ret;
4543
4544 ret = block_exists(hexstr);
4545 free(hexstr);
4546 return ret;
4547}
4548
4549static int block_sort(struct block *blocka, struct block *blockb)
4550{
4551 return blocka->block_no - blockb->block_no;
4552}
4553
4554static void set_blockdiff(const struct work *work)
4555{
4556 unsigned char target[32];
4557 double diff;
4558 uint64_t diff64;
4559
4560 real_block_target(target, work->data);
4561 diff = target_diff(target);
4562 diff64 = diff;
4563
4564 suffix_string(diff64, block_diff, 0);
4565 hashrate_to_bufstr(net_hashrate, diff * 7158278, -1, H2B_SHORT);
4566 current_diff = diff;
4567}
4568
4569static bool_Bool test_work_current(struct work *work)
4570{
4571 bool_Bool ret = true1;
4572 char *hexstr;
4573
4574 if (work->mandatory)
4575 return ret;
4576
4577 uint32_t block_id = ((uint32_t*)(work->data))[1];
4578
4579 /* Hack to work around dud work sneaking into test */
4580 hexstr = bin2hex(work->data + 8, 18);
4581 if (!strncmp(hexstr, "000000000000000000000000000000000000", 36))
4582 goto out_free;
4583
4584 /* Search to see if this block exists yet and if not, consider it a
4585 * new block and set the current block details to this one */
4586 if (!block_exists(hexstr)) {
4587 struct block *s = calloc(sizeof(struct block), 1);
4588 int deleted_block = 0;
4589 ret = false0;
4590
4591 if (unlikely(!s)(!s))
4592 quit (1, "test_work_current OOM");
4593 strcpy(s->hash, hexstr);
4594 s->block_no = new_blocks++;
4595 wr_lock(&blk_lock);
4596 /* Only keep the last hour's worth of blocks in memory since
4597 * work from blocks before this is virtually impossible and we
4598 * want to prevent memory usage from continually rising */
4599 if (HASH_COUNT(blocks)((blocks)?((blocks)->hh.tbl->num_items):0) > 6) {
4600 struct block *oldblock;
4601
4602 HASH_SORT(blocks, block_sort)do { unsigned _hs_i; unsigned _hs_looping,_hs_nmerges,_hs_insize
,_hs_psize,_hs_qsize; struct UT_hash_handle *_hs_p, *_hs_q, *
_hs_e, *_hs_list, *_hs_tail; if (blocks) { _hs_insize = 1; _hs_looping
= 1; _hs_list = &((blocks)->hh); while (_hs_looping) {
_hs_p = _hs_list; _hs_list = ((void*)0); _hs_tail = ((void*)
0); _hs_nmerges = 0; while (_hs_p) { _hs_nmerges++; _hs_q = _hs_p
; _hs_psize = 0; for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i
++ ) { _hs_psize++; _hs_q = (UT_hash_handle*)((_hs_q->next
) ? ((void*)((char*)(_hs_q->next) + (blocks)->hh.tbl->
hho)) : ((void*)0)); if (! (_hs_q) ) break; } _hs_qsize = _hs_insize
; while ((_hs_psize > 0) || ((_hs_qsize > 0) &&
_hs_q )) { if (_hs_psize == 0) { _hs_e = _hs_q; _hs_q = (UT_hash_handle
*)((_hs_q->next) ? ((void*)((char*)(_hs_q->next) + (blocks
)->hh.tbl->hho)) : ((void*)0)); _hs_qsize--; } else if (
(_hs_qsize == 0) || !(_hs_q) ) { _hs_e = _hs_p; _hs_p = (UT_hash_handle
*)((_hs_p->next) ? ((void*)((char*)(_hs_p->next) + (blocks
)->hh.tbl->hho)) : ((void*)0)); _hs_psize--; } else if (
( block_sort((__typeof(blocks))(((void*)(((char*)(_hs_p)) - (
((blocks)->hh.tbl)->hho)))), (__typeof(blocks))(((void*
)(((char*)(_hs_q)) - (((blocks)->hh.tbl)->hho))))) ) <=
0) { _hs_e = _hs_p; _hs_p = (UT_hash_handle*)((_hs_p->next
) ? ((void*)((char*)(_hs_p->next) + (blocks)->hh.tbl->
hho)) : ((void*)0)); _hs_psize--; } else { _hs_e = _hs_q; _hs_q
= (UT_hash_handle*)((_hs_q->next) ? ((void*)((char*)(_hs_q
->next) + (blocks)->hh.tbl->hho)) : ((void*)0)); _hs_qsize
--; } if ( _hs_tail ) { _hs_tail->next = ((_hs_e) ? ((void
*)(((char*)(_hs_e)) - (((blocks)->hh.tbl)->hho))) : ((void
*)0)); } else { _hs_list = _hs_e; } _hs_e->prev = ((_hs_tail
) ? ((void*)(((char*)(_hs_tail)) - (((blocks)->hh.tbl)->
hho))) : ((void*)0)); _hs_tail = _hs_e; } _hs_p = _hs_q; } _hs_tail
->next = ((void*)0); if ( _hs_nmerges <= 1 ) { _hs_looping
=0; (blocks)->hh.tbl->tail = _hs_tail; do { (blocks) = (
__typeof(blocks))(((void*)(((char*)(_hs_list)) - (((blocks)->
hh.tbl)->hho)))); } while(0); } _hs_insize *= 2; } ; } } while
(0)
;
4603 oldblock = blocks;
4604 deleted_block = oldblock->block_no;
4605 HASH_DEL(blocks, oldblock)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((oldblock)->hh.prev == ((void*)0)) && ((oldblock
)->hh.next == ((void*)0)) ) { free((blocks)->hh.tbl->
buckets); ; free((blocks)->hh.tbl); blocks = ((void*)0); }
else { _hd_hh_del = &((oldblock)->hh); if ((oldblock)
== ((void*)(((char*)((blocks)->hh.tbl->tail)) - (((blocks
)->hh.tbl)->hho)))) { (blocks)->hh.tbl->tail = (UT_hash_handle
*)((char*)((oldblock)->hh.prev) + (blocks)->hh.tbl->
hho); } if ((oldblock)->hh.prev) { ((UT_hash_handle*)((char
*)((oldblock)->hh.prev) + (blocks)->hh.tbl->hho))->
next = (oldblock)->hh.next; } else { do { (blocks) = (__typeof
(blocks))((oldblock)->hh.next); } while(0); } if (_hd_hh_del
->next) { ((UT_hash_handle*)((char*)_hd_hh_del->next + (
blocks)->hh.tbl->hho))->prev = _hd_hh_del->prev; }
do { _hd_bkt = ((_hd_hh_del->hashv) & (((blocks)->
hh.tbl->num_buckets) - 1)); } while(0); ((blocks)->hh.tbl
->buckets[_hd_bkt]).count--; if (((blocks)->hh.tbl->
buckets[_hd_bkt]).hh_head == _hd_hh_del) { ((blocks)->hh.tbl
->buckets[_hd_bkt]).hh_head = _hd_hh_del->hh_next; } if
(_hd_hh_del->hh_prev) { _hd_hh_del->hh_prev->hh_next
= _hd_hh_del->hh_next; } if (_hd_hh_del->hh_next) { _hd_hh_del
->hh_next->hh_prev = _hd_hh_del->hh_prev; }; (blocks
)->hh.tbl->num_items--; } ; } while (0)
;
4606 free(oldblock);
4607 }
4608 HASH_ADD_STR(blocks, hash, s)do { unsigned _ha_bkt; (s)->hh.next = ((void*)0); (s)->
hh.key = (char*)&((s)->hash); (s)->hh.keylen = (unsigned
)strlen(s->hash); if (!(blocks)) { blocks = (s); (blocks)->
hh.prev = ((void*)0); do { (blocks)->hh.tbl = (UT_hash_table
*)malloc(sizeof(UT_hash_table)); if (!((blocks)->hh.tbl)) {
exit(-1); } memset((blocks)->hh.tbl, 0, sizeof(UT_hash_table
)); (blocks)->hh.tbl->tail = &((blocks)->hh); (blocks
)->hh.tbl->num_buckets = 32; (blocks)->hh.tbl->log2_num_buckets
= 5; (blocks)->hh.tbl->hho = (char*)(&(blocks)->
hh) - (char*)(blocks); (blocks)->hh.tbl->buckets = (UT_hash_bucket
*)malloc(32*sizeof(struct UT_hash_bucket)); if (! (blocks)->
hh.tbl->buckets) { exit(-1); } memset((blocks)->hh.tbl->
buckets, 0, 32*sizeof(struct UT_hash_bucket)); ; (blocks)->
hh.tbl->signature = 0xa0111fe1; } while(0); } else { (blocks
)->hh.tbl->tail->next = (s); (s)->hh.prev = ((void
*)(((char*)((blocks)->hh.tbl->tail)) - (((blocks)->hh
.tbl)->hho))); (blocks)->hh.tbl->tail = &((s)->
hh); } (blocks)->hh.tbl->num_items++; (s)->hh.tbl = (
blocks)->hh.tbl; do { unsigned _hj_i,_hj_j,_hj_k; char *_hj_key
=(char*)(&((s)->hash)); (s)->hh.hashv = 0xfeedbeef;
_hj_i = _hj_j = 0x9e3779b9; _hj_k = (unsigned)strlen(s->hash
); while (_hj_k >= 12) { _hj_i += (_hj_key[0] + ( (unsigned
)_hj_key[1] << 8 ) + ( (unsigned)_hj_key[2] << 16
) + ( (unsigned)_hj_key[3] << 24 ) ); _hj_j += (_hj_key
[4] + ( (unsigned)_hj_key[5] << 8 ) + ( (unsigned)_hj_key
[6] << 16 ) + ( (unsigned)_hj_key[7] << 24 ) ); (
s)->hh.hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] <<
8 ) + ( (unsigned)_hj_key[10] << 16 ) + ( (unsigned)_hj_key
[11] << 24 ) ); do { _hj_i -= _hj_j; _hj_i -= (s)->hh
.hashv; _hj_i ^= ( (s)->hh.hashv >> 13 ); _hj_j -= (
s)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i << 8 )
; (s)->hh.hashv -= _hj_i; (s)->hh.hashv -= _hj_j; (s)->
hh.hashv ^= ( _hj_j >> 13 ); _hj_i -= _hj_j; _hj_i -= (
s)->hh.hashv; _hj_i ^= ( (s)->hh.hashv >> 12 ); _hj_j
-= (s)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
16 ); (s)->hh.hashv -= _hj_i; (s)->hh.hashv -= _hj_j; (
s)->hh.hashv ^= ( _hj_j >> 5 ); _hj_i -= _hj_j; _hj_i
-= (s)->hh.hashv; _hj_i ^= ( (s)->hh.hashv >> 3 )
; _hj_j -= (s)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i
<< 10 ); (s)->hh.hashv -= _hj_i; (s)->hh.hashv -=
_hj_j; (s)->hh.hashv ^= ( _hj_j >> 15 ); } while (0
); _hj_key += 12; _hj_k -= 12; } (s)->hh.hashv += strlen(s
->hash); switch ( _hj_k ) { case 11: (s)->hh.hashv += (
(unsigned)_hj_key[10] << 24 ); case 10: (s)->hh.hashv
+= ( (unsigned)_hj_key[9] << 16 ); case 9: (s)->hh.
hashv += ( (unsigned)_hj_key[8] << 8 ); case 8: _hj_j +=
( (unsigned)_hj_key[7] << 24 ); case 7: _hj_j += ( (unsigned
)_hj_key[6] << 16 ); case 6: _hj_j += ( (unsigned)_hj_key
[5] << 8 ); case 5: _hj_j += _hj_key[4]; case 4: _hj_i +=
( (unsigned)_hj_key[3] << 24 ); case 3: _hj_i += ( (unsigned
)_hj_key[2] << 16 ); case 2: _hj_i += ( (unsigned)_hj_key
[1] << 8 ); case 1: _hj_i += _hj_key[0]; } do { _hj_i -=
_hj_j; _hj_i -= (s)->hh.hashv; _hj_i ^= ( (s)->hh.hashv
>> 13 ); _hj_j -= (s)->hh.hashv; _hj_j -= _hj_i; _hj_j
^= ( _hj_i << 8 ); (s)->hh.hashv -= _hj_i; (s)->
hh.hashv -= _hj_j; (s)->hh.hashv ^= ( _hj_j >> 13 );
_hj_i -= _hj_j; _hj_i -= (s)->hh.hashv; _hj_i ^= ( (s)->
hh.hashv >> 12 ); _hj_j -= (s)->hh.hashv; _hj_j -= _hj_i
; _hj_j ^= ( _hj_i << 16 ); (s)->hh.hashv -= _hj_i; (
s)->hh.hashv -= _hj_j; (s)->hh.hashv ^= ( _hj_j >>
5 ); _hj_i -= _hj_j; _hj_i -= (s)->hh.hashv; _hj_i ^= ( (
s)->hh.hashv >> 3 ); _hj_j -= (s)->hh.hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 10 ); (s)->hh.hashv -=
_hj_i; (s)->hh.hashv -= _hj_j; (s)->hh.hashv ^= ( _hj_j
>> 15 ); } while (0); _ha_bkt = (s)->hh.hashv &
((blocks)->hh.tbl->num_buckets-1); } while(0); do { (blocks
)->hh.tbl->buckets[_ha_bkt].count++; (&(s)->hh)->
hh_next = (blocks)->hh.tbl->buckets[_ha_bkt].hh_head; (
&(s)->hh)->hh_prev = ((void*)0); if ((blocks)->hh
.tbl->buckets[_ha_bkt].hh_head) { ((blocks)->hh.tbl->
buckets[_ha_bkt]).hh_head->hh_prev = (&(s)->hh); } (
(blocks)->hh.tbl->buckets[_ha_bkt]).hh_head=&(s)->
hh; if ((blocks)->hh.tbl->buckets[_ha_bkt].count >= (
((blocks)->hh.tbl->buckets[_ha_bkt].expand_mult+1) * 10
) && (&(s)->hh)->tbl->noexpand != 1) { do
{ unsigned _he_bkt; unsigned _he_bkt_i; struct UT_hash_handle
*_he_thh, *_he_hh_nxt; UT_hash_bucket *_he_new_buckets, *_he_newbkt
; _he_new_buckets = (UT_hash_bucket*)malloc(2 * (&(s)->
hh)->tbl->num_buckets * sizeof(struct UT_hash_bucket));
if (!_he_new_buckets) { exit(-1); } memset(_he_new_buckets, 0
, 2 * (&(s)->hh)->tbl->num_buckets * sizeof(struct
UT_hash_bucket)); (&(s)->hh)->tbl->ideal_chain_maxlen
= ((&(s)->hh)->tbl->num_items >> ((&(
s)->hh)->tbl->log2_num_buckets+1)) + (((&(s)->
hh)->tbl->num_items & (((&(s)->hh)->tbl->
num_buckets*2)-1)) ? 1 : 0); (&(s)->hh)->tbl->nonideal_items
= 0; for(_he_bkt_i = 0; _he_bkt_i < (&(s)->hh)->
tbl->num_buckets; _he_bkt_i++) { _he_thh = (&(s)->hh
)->tbl->buckets[ _he_bkt_i ].hh_head; while (_he_thh) {
_he_hh_nxt = _he_thh->hh_next; do { _he_bkt = ((_he_thh->
hashv) & (((&(s)->hh)->tbl->num_buckets*2) -
1)); } while(0); _he_newbkt = &(_he_new_buckets[ _he_bkt
]); if (++(_he_newbkt->count) > (&(s)->hh)->
tbl->ideal_chain_maxlen) { (&(s)->hh)->tbl->nonideal_items
++; _he_newbkt->expand_mult = _he_newbkt->count / (&
(s)->hh)->tbl->ideal_chain_maxlen; } _he_thh->hh_prev
= ((void*)0); _he_thh->hh_next = _he_newbkt->hh_head; if
(_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =
_he_thh; _he_newbkt->hh_head = _he_thh; _he_thh = _he_hh_nxt
; } } free((&(s)->hh)->tbl->buckets); (&(s)->
hh)->tbl->num_buckets *= 2; (&(s)->hh)->tbl->
log2_num_buckets++; (&(s)->hh)->tbl->buckets = _he_new_buckets
; (&(s)->hh)->tbl->ineff_expands = ((&(s)->
hh)->tbl->nonideal_items > ((&(s)->hh)->tbl
->num_items >> 1)) ? ((&(s)->hh)->tbl->
ineff_expands+1) : 0; if ((&(s)->hh)->tbl->ineff_expands
> 1) { (&(s)->hh)->tbl->noexpand=1; ; } ; } while
(0); } } while(0); ; ; ; } while(0)
;
4609 set_blockdiff(work);
4610 wr_unlock(&blk_lock);
4611 work->pool->block_id = block_id;
4612 if (deleted_block)
4613 applog(LOG_DEBUG7, "Deleted block %d from database", deleted_block);
4614 template_nonce = 0;
4615 set_curblock(hexstr, &work->data[4]);
4616 if (unlikely(new_blocks == 1)(new_blocks == 1))
4617 goto out_free;
4618
4619 if (!work->stratum) {
4620 if (work->longpoll) {
4621 applog(LOG_NOTICE5, "Longpoll from pool %d detected new block",
4622 work->pool->pool_no);
4623 } else if (have_longpoll)
4624 applog(LOG_NOTICE5, "New block detected on network before longpoll");
4625 else
4626 applog(LOG_NOTICE5, "New block detected on network");
4627 }
4628 restart_threads();
4629 } else {
4630 bool_Bool restart = false0;
4631 struct pool *curpool = NULL((void*)0);
4632 if (unlikely(work->pool->block_id != block_id)(work->pool->block_id != block_id)) {
4633 bool_Bool was_active = work->pool->block_id != 0;
4634 work->pool->block_id = block_id;
4635 if (!work->longpoll)
4636 update_last_work(work);
4637 if (was_active) { // Pool actively changed block
4638 if (work->pool == (curpool = current_pool()))
4639 restart = true1;
4640 if (block_id == current_block_id) {
4641 // Caught up, only announce if this pool is the one in use
4642 if (restart)
4643 applog(LOG_NOTICE5, "%s %d caught up to new block",
4644 work->longpoll ? "Longpoll from pool" : "Pool",
4645 work->pool->pool_no);
4646 } else {
4647 // Switched to a block we know, but not the latest... why?
4648 // This might detect pools trying to double-spend or 51%,
4649 // but let's not make any accusations until it's had time
4650 // in the real world.
4651 free(hexstr);
4652 hexstr = blkhashstr(&work->data[4]);
4653 applog(LOG_WARNING4, "%s %d is issuing work for an old block: %s",
4654 work->longpoll ? "Longpoll from pool" : "Pool",
4655 work->pool->pool_no,
4656 hexstr);
4657 }
4658 }
4659 }
4660 if (work->longpoll) {
4661 ++work->pool->work_restart_id;
4662 update_last_work(work);
4663 if ((!restart) && work->pool == current_pool()) {
4664 applog(
4665 (opt_quiet_work_updates ? LOG_DEBUG7 : LOG_NOTICE5),
4666 "Longpoll from pool %d requested work update",
4667 work->pool->pool_no);
4668 restart = true1;
4669 }
4670 }
4671 if (restart)
4672 restart_threads();
4673 }
4674 work->longpoll = false0;
4675out_free:
4676 free(hexstr);
4677 return ret;
4678}
4679
4680static int tv_sort(struct work *worka, struct work *workb)
4681{
4682 return worka->tv_staged.tv_sec - workb->tv_staged.tv_sec;
4683}
4684
4685static bool_Bool work_rollable(struct work *work)
4686{
4687 return (!work->clone && work->rolltime);
4688}
4689
4690static bool_Bool hash_push(struct work *work)
4691{
4692 bool_Bool rc = true1;
4693
4694 mutex_lock(stgd_lock);
4695 if (work_rollable(work))
4696 staged_rollable++;
4697 if (likely(!getq->frozen)(!getq->frozen)) {
4698 HASH_ADD_INT(staged_work, id, work)do { unsigned _ha_bkt; (work)->hh.next = ((void*)0); (work
)->hh.key = (char*)&((work)->id); (work)->hh.keylen
= (unsigned)sizeof(int); if (!(staged_work)) { staged_work =
(work); (staged_work)->hh.prev = ((void*)0); do { (staged_work
)->hh.tbl = (UT_hash_table*)malloc(sizeof(UT_hash_table));
if (!((staged_work)->hh.tbl)) { exit(-1); } memset((staged_work
)->hh.tbl, 0, sizeof(UT_hash_table)); (staged_work)->hh
.tbl->tail = &((staged_work)->hh); (staged_work)->
hh.tbl->num_buckets = 32; (staged_work)->hh.tbl->log2_num_buckets
= 5; (staged_work)->hh.tbl->hho = (char*)(&(staged_work
)->hh) - (char*)(staged_work); (staged_work)->hh.tbl->
buckets = (UT_hash_bucket*)malloc(32*sizeof(struct UT_hash_bucket
)); if (! (staged_work)->hh.tbl->buckets) { exit(-1); }
memset((staged_work)->hh.tbl->buckets, 0, 32*sizeof(struct
UT_hash_bucket)); ; (staged_work)->hh.tbl->signature =
0xa0111fe1; } while(0); } else { (staged_work)->hh.tbl->
tail->next = (work); (work)->hh.prev = ((void*)(((char*
)((staged_work)->hh.tbl->tail)) - (((staged_work)->hh
.tbl)->hho))); (staged_work)->hh.tbl->tail = &((
work)->hh); } (staged_work)->hh.tbl->num_items++; (work
)->hh.tbl = (staged_work)->hh.tbl; do { unsigned _hj_i,
_hj_j,_hj_k; char *_hj_key=(char*)(&((work)->id)); (work
)->hh.hashv = 0xfeedbeef; _hj_i = _hj_j = 0x9e3779b9; _hj_k
= (unsigned)sizeof(int); while (_hj_k >= 12) { _hj_i += (
_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) + ( (unsigned
)_hj_key[2] << 16 ) + ( (unsigned)_hj_key[3] << 24
) ); _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8
) + ( (unsigned)_hj_key[6] << 16 ) + ( (unsigned)_hj_key
[7] << 24 ) ); (work)->hh.hashv += (_hj_key[8] + ( (
unsigned)_hj_key[9] << 8 ) + ( (unsigned)_hj_key[10] <<
16 ) + ( (unsigned)_hj_key[11] << 24 ) ); do { _hj_i -=
_hj_j; _hj_i -= (work)->hh.hashv; _hj_i ^= ( (work)->hh
.hashv >> 13 ); _hj_j -= (work)->hh.hashv; _hj_j -= _hj_i
; _hj_j ^= ( _hj_i << 8 ); (work)->hh.hashv -= _hj_i
; (work)->hh.hashv -= _hj_j; (work)->hh.hashv ^= ( _hj_j
>> 13 ); _hj_i -= _hj_j; _hj_i -= (work)->hh.hashv;
_hj_i ^= ( (work)->hh.hashv >> 12 ); _hj_j -= (work
)->hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i << 16 )
; (work)->hh.hashv -= _hj_i; (work)->hh.hashv -= _hj_j;
(work)->hh.hashv ^= ( _hj_j >> 5 ); _hj_i -= _hj_j;
_hj_i -= (work)->hh.hashv; _hj_i ^= ( (work)->hh.hashv
>> 3 ); _hj_j -= (work)->hh.hashv; _hj_j -= _hj_i; _hj_j
^= ( _hj_i << 10 ); (work)->hh.hashv -= _hj_i; (work
)->hh.hashv -= _hj_j; (work)->hh.hashv ^= ( _hj_j >>
15 ); } while (0); _hj_key += 12; _hj_k -= 12; } (work)->
hh.hashv += sizeof(int); switch ( _hj_k ) { case 11: (work)->
hh.hashv += ( (unsigned)_hj_key[10] << 24 ); case 10: (
work)->hh.hashv += ( (unsigned)_hj_key[9] << 16 ); case
9: (work)->hh.hashv += ( (unsigned)_hj_key[8] << 8 )
; case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); case
7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); case 6: _hj_j
+= ( (unsigned)_hj_key[5] << 8 ); case 5: _hj_j += _hj_key
[4]; case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); case
3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); case 2: _hj_i
+= ( (unsigned)_hj_key[1] << 8 ); case 1: _hj_i += _hj_key
[0]; } do { _hj_i -= _hj_j; _hj_i -= (work)->hh.hashv; _hj_i
^= ( (work)->hh.hashv >> 13 ); _hj_j -= (work)->
hh.hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i << 8 ); (work
)->hh.hashv -= _hj_i; (work)->hh.hashv -= _hj_j; (work)
->hh.hashv ^= ( _hj_j >> 13 ); _hj_i -= _hj_j; _hj_i
-= (work)->hh.hashv; _hj_i ^= ( (work)->hh.hashv >>
12 ); _hj_j -= (work)->hh.hashv; _hj_j -= _hj_i; _hj_j ^=
( _hj_i << 16 ); (work)->hh.hashv -= _hj_i; (work)->
hh.hashv -= _hj_j; (work)->hh.hashv ^= ( _hj_j >> 5 )
; _hj_i -= _hj_j; _hj_i -= (work)->hh.hashv; _hj_i ^= ( (work
)->hh.hashv >> 3 ); _hj_j -= (work)->hh.hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 10 ); (work)->hh.hashv
-= _hj_i; (work)->hh.hashv -= _hj_j; (work)->hh.hashv ^=
( _hj_j >> 15 ); } while (0); _ha_bkt = (work)->hh.
hashv & ((staged_work)->hh.tbl->num_buckets-1); } while
(0); do { (staged_work)->hh.tbl->buckets[_ha_bkt].count
++; (&(work)->hh)->hh_next = (staged_work)->hh.tbl
->buckets[_ha_bkt].hh_head; (&(work)->hh)->hh_prev
= ((void*)0); if ((staged_work)->hh.tbl->buckets[_ha_bkt
].hh_head) { ((staged_work)->hh.tbl->buckets[_ha_bkt]).
hh_head->hh_prev = (&(work)->hh); } ((staged_work)->
hh.tbl->buckets[_ha_bkt]).hh_head=&(work)->hh; if (
(staged_work)->hh.tbl->buckets[_ha_bkt].count >= (((
staged_work)->hh.tbl->buckets[_ha_bkt].expand_mult+1) *
10) && (&(work)->hh)->tbl->noexpand != 1
) { do { unsigned _he_bkt; unsigned _he_bkt_i; struct UT_hash_handle
*_he_thh, *_he_hh_nxt; UT_hash_bucket *_he_new_buckets, *_he_newbkt
; _he_new_buckets = (UT_hash_bucket*)malloc(2 * (&(work)->
hh)->tbl->num_buckets * sizeof(struct UT_hash_bucket));
if (!_he_new_buckets) { exit(-1); } memset(_he_new_buckets, 0
, 2 * (&(work)->hh)->tbl->num_buckets * sizeof(struct
UT_hash_bucket)); (&(work)->hh)->tbl->ideal_chain_maxlen
= ((&(work)->hh)->tbl->num_items >> ((&
(work)->hh)->tbl->log2_num_buckets+1)) + (((&(work
)->hh)->tbl->num_items & (((&(work)->hh)->
tbl->num_buckets*2)-1)) ? 1 : 0); (&(work)->hh)->
tbl->nonideal_items = 0; for(_he_bkt_i = 0; _he_bkt_i <
(&(work)->hh)->tbl->num_buckets; _he_bkt_i++) {
_he_thh = (&(work)->hh)->tbl->buckets[ _he_bkt_i
].hh_head; while (_he_thh) { _he_hh_nxt = _he_thh->hh_next
; do { _he_bkt = ((_he_thh->hashv) & (((&(work)->
hh)->tbl->num_buckets*2) - 1)); } while(0); _he_newbkt =
&(_he_new_buckets[ _he_bkt ]); if (++(_he_newbkt->count
) > (&(work)->hh)->tbl->ideal_chain_maxlen) {
(&(work)->hh)->tbl->nonideal_items++; _he_newbkt
->expand_mult = _he_newbkt->count / (&(work)->hh
)->tbl->ideal_chain_maxlen; } _he_thh->hh_prev = ((void
*)0); _he_thh->hh_next = _he_newbkt->hh_head; if (_he_newbkt
->hh_head) _he_newbkt->hh_head->hh_prev = _he_thh; _he_newbkt
->hh_head = _he_thh; _he_thh = _he_hh_nxt; } } free((&
(work)->hh)->tbl->buckets); (&(work)->hh)->
tbl->num_buckets *= 2; (&(work)->hh)->tbl->log2_num_buckets
++; (&(work)->hh)->tbl->buckets = _he_new_buckets
; (&(work)->hh)->tbl->ineff_expands = ((&(work
)->hh)->tbl->nonideal_items > ((&(work)->hh
)->tbl->num_items >> 1)) ? ((&(work)->hh)->
tbl->ineff_expands+1) : 0; if ((&(work)->hh)->tbl
->ineff_expands > 1) { (&(work)->hh)->tbl->
noexpand=1; ; } ; } while(0); } } while(0); ; ; ; } while(0)
;
4699 HASH_SORT(staged_work, tv_sort)do { unsigned _hs_i; unsigned _hs_looping,_hs_nmerges,_hs_insize
,_hs_psize,_hs_qsize; struct UT_hash_handle *_hs_p, *_hs_q, *
_hs_e, *_hs_list, *_hs_tail; if (staged_work) { _hs_insize = 1
; _hs_looping = 1; _hs_list = &((staged_work)->hh); while
(_hs_looping) { _hs_p = _hs_list; _hs_list = ((void*)0); _hs_tail
= ((void*)0); _hs_nmerges = 0; while (_hs_p) { _hs_nmerges++
; _hs_q = _hs_p; _hs_psize = 0; for ( _hs_i = 0; _hs_i < _hs_insize
; _hs_i++ ) { _hs_psize++; _hs_q = (UT_hash_handle*)((_hs_q->
next) ? ((void*)((char*)(_hs_q->next) + (staged_work)->
hh.tbl->hho)) : ((void*)0)); if (! (_hs_q) ) break; } _hs_qsize
= _hs_insize; while ((_hs_psize > 0) || ((_hs_qsize > 0
) && _hs_q )) { if (_hs_psize == 0) { _hs_e = _hs_q; _hs_q
= (UT_hash_handle*)((_hs_q->next) ? ((void*)((char*)(_hs_q
->next) + (staged_work)->hh.tbl->hho)) : ((void*)0))
; _hs_qsize--; } else if ( (_hs_qsize == 0) || !(_hs_q) ) { _hs_e
= _hs_p; _hs_p = (UT_hash_handle*)((_hs_p->next) ? ((void
*)((char*)(_hs_p->next) + (staged_work)->hh.tbl->hho
)) : ((void*)0)); _hs_psize--; } else if (( tv_sort((__typeof
(staged_work))(((void*)(((char*)(_hs_p)) - (((staged_work)->
hh.tbl)->hho)))), (__typeof(staged_work))(((void*)(((char*
)(_hs_q)) - (((staged_work)->hh.tbl)->hho))))) ) <= 0
) { _hs_e = _hs_p; _hs_p = (UT_hash_handle*)((_hs_p->next)
? ((void*)((char*)(_hs_p->next) + (staged_work)->hh.tbl
->hho)) : ((void*)0)); _hs_psize--; } else { _hs_e = _hs_q
; _hs_q = (UT_hash_handle*)((_hs_q->next) ? ((void*)((char
*)(_hs_q->next) + (staged_work)->hh.tbl->hho)) : ((void
*)0)); _hs_qsize--; } if ( _hs_tail ) { _hs_tail->next = (
(_hs_e) ? ((void*)(((char*)(_hs_e)) - (((staged_work)->hh.
tbl)->hho))) : ((void*)0)); } else { _hs_list = _hs_e; } _hs_e
->prev = ((_hs_tail) ? ((void*)(((char*)(_hs_tail)) - (((staged_work
)->hh.tbl)->hho))) : ((void*)0)); _hs_tail = _hs_e; } _hs_p
= _hs_q; } _hs_tail->next = ((void*)0); if ( _hs_nmerges <=
1 ) { _hs_looping=0; (staged_work)->hh.tbl->tail = _hs_tail
; do { (staged_work) = (__typeof(staged_work))(((void*)(((char
*)(_hs_list)) - (((staged_work)->hh.tbl)->hho)))); } while
(0); } _hs_insize *= 2; } ; } } while (0)
;
4700 } else
4701 rc = false0;
4702 pthread_cond_broadcast(&getq->cond);
4703 mutex_unlock(stgd_lock);
4704
4705 return rc;
4706}
4707
4708static void *stage_thread(void *userdata)
4709{
4710 struct thr_info *mythr = userdata;
4711 bool_Bool ok = true1;
4712
4713#ifndef HAVE_PTHREAD_CANCEL1
4714 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUSPTHREAD_CANCEL_ASYNCHRONOUS, NULL((void*)0));
4715#endif
4716
4717 RenameThread("stage");
4718
4719 while (ok) {
4720 struct work *work = NULL((void*)0);
4721
4722 applog(LOG_DEBUG7, "Popping work to stage thread");
4723
4724 work = tq_pop(mythr->q, NULL((void*)0));
4725 if (unlikely(!work)(!work)) {
4726 applog(LOG_ERR3, "Failed to tq_pop in stage_thread");
4727 ok = false0;
4728 break;
4729 }
4730 work->work_restart_id = work->pool->work_restart_id;
4731
4732 test_work_current(work);
4733
4734 applog(LOG_DEBUG7, "Pushing work to getwork queue (queued=%c)", work->queued?'Y':'N');
4735
4736 if (unlikely(!hash_push(work))(!hash_push(work))) {
4737 applog(LOG_WARNING4, "Failed to hash_push in stage_thread");
4738 continue;
4739 }
4740 }
4741
4742 tq_freeze(mythr->q);
4743 return NULL((void*)0);
4744}
4745
4746static void stage_work(struct work *work)
4747{
4748 applog(LOG_DEBUG7, "Pushing work from pool %d to hash queue", work->pool->pool_no);
4749 work->work_restart_id = work->pool->work_restart_id;
4750 test_work_current(work);
4751 hash_push(work);
4752}
4753
4754#ifdef HAVE_CURSES1
4755int curses_int(const char *query)
4756{
4757 int ret;
4758 char *cvar;
4759
4760 cvar = curses_input(query);
4761 ret = atoi(cvar);
4762 free(cvar);
4763 return ret;
4764}
4765#endif
4766
4767#ifdef HAVE_CURSES1
4768static bool_Bool input_pool(bool_Bool live);
4769#endif
4770
4771#ifdef HAVE_CURSES1
4772static void display_pool_summary(struct pool *pool)
4773{
4774 double efficiency = 0.0;
4775
4776 if (curses_active_locked()) {
4777 wlog("Pool: %s\n", pool->rpc_url);
4778 if (pool->solved)
4779 wlog("SOLVED %d BLOCK%s!\n", pool->solved, pool->solved > 1 ? "S" : "");
4780 wlog("%s own long-poll support\n", pool->lp_url ? "Has" : "Does not have");
4781 wlog(" Queued work requests: %d\n", pool->getwork_requested);
4782 wlog(" Share submissions: %d\n", pool->accepted + pool->rejected);
4783 wlog(" Accepted shares: %d\n", pool->accepted);
4784 wlog(" Rejected shares: %d\n", pool->rejected);
4785 wlog(" Accepted difficulty shares: %1.f\n", pool->diff_accepted);
4786 wlog(" Rejected difficulty shares: %1.f\n", pool->diff_rejected);
4787 if (pool->accepted || pool->rejected)
4788 wlog(" Reject ratio: %.1f%%\n", (double)(pool->rejected * 100) / (double)(pool->accepted + pool->rejected));
4789 uint64_t pool_bytes_xfer = pool->cgminer_pool_stats.net_bytes_received + pool->cgminer_pool_stats.net_bytes_sent;
4790 efficiency = pool_bytes_xfer ? pool->diff_accepted * 2048. / pool_bytes_xfer : 0.0;
4791 wlog(" Efficiency (accepted * difficulty / 2 KB): %.2f\n", efficiency);
4792
4793 wlog(" Discarded work due to new blocks: %d\n", pool->discarded_work);
4794 wlog(" Stale submissions discarded due to new blocks: %d\n", pool->stale_shares);
4795 wlog(" Unable to get work from server occasions: %d\n", pool->getfail_occasions);
4796 wlog(" Submitting work remotely delay occasions: %d\n\n", pool->remotefail_occasions);
4797 unlock_curses();
4798 }
4799}
4800#endif
4801
4802/* We can't remove the memory used for this struct pool because there may
4803 * still be work referencing it. We just remove it from the pools list */
4804void remove_pool(struct pool *pool)
4805{
4806 int i, last_pool = total_pools - 1;
4807 struct pool *other;
4808
4809 /* Boost priority of any lower prio than this one */
4810 for (i = 0; i < total_pools; i++) {
4811 other = pools[i];
4812 if (other->prio > pool->prio)
4813 other->prio--;
4814 }
4815
4816 if (pool->pool_no < last_pool) {
4817 /* Swap the last pool for this one */
4818 (pools[last_pool])->pool_no = pool->pool_no;
4819 pools[pool->pool_no] = pools[last_pool];
4820 }
4821 /* Give it an invalid number */
4822 pool->pool_no = total_pools;
4823 pool->removed = true1;
4824 pool->has_stratum = false0;
4825 total_pools--;
4826}
4827
4828/* add a mutex if this needs to be thread safe in the future */
4829static struct JE {
4830 char *buf;
4831 struct JE *next;
4832} *jedata = NULL((void*)0);
4833
4834static void json_escape_free()
4835{
4836 struct JE *jeptr = jedata;
4837 struct JE *jenext;
4838
4839 jedata = NULL((void*)0);
4840
4841 while (jeptr) {
4842 jenext = jeptr->next;
4843 free(jeptr->buf);
4844 free(jeptr);
4845 jeptr = jenext;
4846 }
4847}
4848
4849static char *json_escape(char *str)
4850{
4851 struct JE *jeptr;
4852 char *buf, *ptr;
4853
4854 /* 2x is the max, may as well just allocate that */
4855 ptr = buf = malloc(strlen(str) * 2 + 1);
4856
4857 jeptr = malloc(sizeof(*jeptr));
4858
4859 jeptr->buf = buf;
4860 jeptr->next = jedata;
4861 jedata = jeptr;
4862
4863 while (*str) {
4864 if (*str == '\\' || *str == '"')
4865 *(ptr++) = '\\';
4866
4867 *(ptr++) = *(str++);
4868 }
4869
4870 *ptr = '\0';
4871
4872 return buf;
4873}
4874
4875void write_config(FILE *fcfg)
4876{
4877 int i;
4878
4879 /* Write pool values */
4880 fputs("{\n\"pools\" : [", fcfg);
4881 for(i = 0; i < total_pools; i++) {
4882 fprintf(fcfg, "%s\n\t{\n\t\t\"url\" : \"%s\",", i > 0 ? "," : "", json_escape(pools[i]->rpc_url));
4883 if (pools[i]->rpc_proxy)
4884 fprintf(fcfg, "\n\t\t\"pool-proxy\" : \"%s\",", json_escape(pools[i]->rpc_proxy));
4885 fprintf(fcfg, "\n\t\t\"user\" : \"%s\",", json_escape(pools[i]->rpc_user));
4886 fprintf(fcfg, "\n\t\t\"pass\" : \"%s\",", json_escape(pools[i]->rpc_pass));
4887 fprintf(fcfg, "\n\t\t\"pool-priority\" : \"%d\"", pools[i]->prio);
4888 if (pools[i]->force_rollntime)
4889 fprintf(fcfg, ",\n\t\t\"force-rollntime\" : %d", pools[i]->force_rollntime);
4890 fprintf(fcfg, "\n\t}");
4891 }
4892 fputs("\n]\n", fcfg);
4893
4894#ifdef HAVE_OPENCL1
4895 if (nDevs) {
4896 /* Write GPU device values */
4897 fputs(",\n\"intensity\" : \"", fcfg);
4898 for(i = 0; i < nDevs; i++)
4899 fprintf(fcfg, gpus[i].dynamic ? "%sd" : "%s%d", i > 0 ? "," : "", gpus[i].intensity);
4900 fputs("\",\n\"vectors\" : \"", fcfg);
4901 for(i = 0; i < nDevs; i++)
4902 fprintf(fcfg, "%s%d", i > 0 ? "," : "",
4903 gpus[i].vwidth);
4904 fputs("\",\n\"worksize\" : \"", fcfg);
4905 for(i = 0; i < nDevs; i++)
4906 fprintf(fcfg, "%s%d", i > 0 ? "," : "",
4907 (int)gpus[i].work_size);
4908 fputs("\",\n\"kernel\" : \"", fcfg);
4909 for(i = 0; i < nDevs; i++) {
4910 fprintf(fcfg, "%s", i > 0 ? "," : "");
4911 switch (gpus[i].kernel) {
4912 case KL_NONE: // Shouldn't happen
4913 break;
4914 case KL_POCLBM:
4915 fprintf(fcfg, "poclbm");
4916 break;
4917 case KL_PHATK:
4918 fprintf(fcfg, "phatk");
4919 break;
4920 case KL_DIAKGCN:
4921 fprintf(fcfg, "diakgcn");
4922 break;
4923 case KL_DIABLO:
4924 fprintf(fcfg, "diablo");
4925 break;
4926 case KL_SCRYPT:
4927 fprintf(fcfg, "scrypt");
4928 break;
4929 }
4930 }
4931#ifdef USE_SCRYPT1
4932 fputs("\",\n\"lookup-gap\" : \"", fcfg);
4933 for(i = 0; i < nDevs; i++)
4934 fprintf(fcfg, "%s%d", i > 0 ? "," : "",
4935 (int)gpus[i].opt_lg);
4936 fputs("\",\n\"thread-concurrency\" : \"", fcfg);
4937 for(i = 0; i < nDevs; i++)
4938 fprintf(fcfg, "%s%d", i > 0 ? "," : "",
4939 (int)gpus[i].opt_tc);
4940 fputs("\",\n\"shaders\" : \"", fcfg);
4941 for(i = 0; i < nDevs; i++)
4942 fprintf(fcfg, "%s%d", i > 0 ? "," : "",
4943 (int)gpus[i].shaders);
4944#endif
4945#ifdef HAVE_ADL1
4946 fputs("\",\n\"gpu-engine\" : \"", fcfg);
4947 for(i = 0; i < nDevs; i++)
4948 fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "", gpus[i].min_engine, gpus[i].gpu_engine);
4949 fputs("\",\n\"gpu-fan\" : \"", fcfg);
4950 for(i = 0; i < nDevs; i++)
4951 fprintf(fcfg, "%s%d-%d", i > 0 ? "," : "", gpus[i].min_fan, gpus[i].gpu_fan);
4952 fputs("\",\n\"gpu-memclock\" : \"", fcfg);
4953 for(i = 0; i < nDevs; i++)
4954 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_memclock);
4955 fputs("\",\n\"gpu-memdiff\" : \"", fcfg);
4956 for(i = 0; i < nDevs; i++)
4957 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_memdiff);
4958 fputs("\",\n\"gpu-powertune\" : \"", fcfg);
4959 for(i = 0; i < nDevs; i++)
4960 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].gpu_powertune);
4961 fputs("\",\n\"gpu-vddc\" : \"", fcfg);
4962 for(i = 0; i < nDevs; i++)
4963 fprintf(fcfg, "%s%1.3f", i > 0 ? "," : "", gpus[i].gpu_vddc);
4964 fputs("\",\n\"temp-cutoff\" : \"", fcfg);
4965 for(i = 0; i < nDevs; i++)
4966 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].cutofftemp);
4967 fputs("\",\n\"temp-overheat\" : \"", fcfg);
4968 for(i = 0; i < nDevs; i++)
4969 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].adl.overtemp);
4970 fputs("\",\n\"temp-target\" : \"", fcfg);
4971 for(i = 0; i < nDevs; i++)
4972 fprintf(fcfg, "%s%d", i > 0 ? "," : "", gpus[i].targettemp);
4973#endif
4974 fputs("\"", fcfg);
4975 }
4976#endif
4977#ifdef HAVE_ADL1
4978 if (opt_reorder)
4979 fprintf(fcfg, ",\n\"gpu-reorder\" : true");
4980#endif
4981#ifdef WANT_CPUMINE1
4982 fprintf(fcfg, ",\n\"algo\" : \"%s\"", algo_names[opt_algo]);
4983#endif
4984
4985 /* Simple bool and int options */
4986 struct opt_table *opt;
4987 for (opt = opt_config_table; opt->type != OPT_END; opt++) {
4988 char *p, *name = strdup(opt->names);
4989 for (p = strtok(name, "|"); p; p = strtok(NULL((void*)0), "|")) {
4990 if (p[1] != '-')
4991 continue;
4992 if (opt->type & OPT_NOARG &&
4993 ((void *)opt->cb == (void *)opt_set_bool || (void *)opt->cb == (void *)opt_set_invbool) &&
4994 (*(bool_Bool *)opt->u.arg == ((void *)opt->cb == (void *)opt_set_bool)))
4995 fprintf(fcfg, ",\n\"%s\" : true", p+2);
4996
4997 if (opt->type & OPT_HASARG &&
4998 ((void *)opt->cb_arg == (void *)set_int_0_to_9999 ||
4999 (void *)opt->cb_arg == (void *)set_int_1_to_65535 ||
5000 (void *)opt->cb_arg == (void *)set_int_0_to_10 ||
5001 (void *)opt->cb_arg == (void *)set_int_1_to_10) &&
5002 opt->desc != opt_hidden &&
5003 0 <= *(int *)opt->u.arg)
5004 fprintf(fcfg, ",\n\"%s\" : \"%d\"", p+2, *(int *)opt->u.arg);
5005 }
5006 }
5007
5008 /* Special case options */
5009 fprintf(fcfg, ",\n\"shares\" : \"%d\"", opt_shares);
5010 if (pool_strategy == POOL_BALANCE)
5011 fputs(",\n\"balance\" : true", fcfg);
5012 if (pool_strategy == POOL_LOADBALANCE)
5013 fputs(",\n\"load-balance\" : true", fcfg);
5014 if (pool_strategy == POOL_ROUNDROBIN)
5015 fputs(",\n\"round-robin\" : true", fcfg);
5016 if (pool_strategy == POOL_ROTATE)
5017 fprintf(fcfg, ",\n\"rotate\" : \"%d\"", opt_rotate_period);
5018#if defined(unix1)
5019 if (opt_stderr_cmd && *opt_stderr_cmd)
5020 fprintf(fcfg, ",\n\"monitor\" : \"%s\"", json_escape(opt_stderr_cmd));
5021#endif // defined(unix)
5022 if (opt_kernel_path && *opt_kernel_path) {
5023 char *kpath = strdup(opt_kernel_path);
5024 if (kpath[strlen(kpath)-1] == '/')
5025 kpath[strlen(kpath)-1] = 0;
5026 fprintf(fcfg, ",\n\"kernel-path\" : \"%s\"", json_escape(kpath));
5027 }
5028 if (schedstart.enable)
5029 fprintf(fcfg, ",\n\"sched-time\" : \"%d:%d\"", schedstart.tm.tm_hour, schedstart.tm.tm_min);
5030 if (schedstop.enable)
5031 fprintf(fcfg, ",\n\"stop-time\" : \"%d:%d\"", schedstop.tm.tm_hour, schedstop.tm.tm_min);
5032 if (opt_socks_proxy && *opt_socks_proxy)
5033 fprintf(fcfg, ",\n\"socks-proxy\" : \"%s\"", json_escape(opt_socks_proxy));
5034#ifdef HAVE_OPENCL1
5035 for(i = 0; i < nDevs; i++)
5036 if (gpus[i].deven == DEV_DISABLED)
5037 break;
5038 if (i < nDevs)
5039 for (i = 0; i < nDevs; i++)
5040 if (gpus[i].deven != DEV_DISABLED)
5041 fprintf(fcfg, ",\n\"device\" : \"%d\"", i);
5042#endif
5043 if (opt_api_allow)
5044 fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow));
5045 if (strcmp(opt_api_description, PACKAGE_STRING"bfgminer 3.0.0") != 0)
5046 fprintf(fcfg, ",\n\"api-description\" : \"%s\"", json_escape(opt_api_description));
5047 if (opt_api_groups)
5048 fprintf(fcfg, ",\n\"api-groups\" : \"%s\"", json_escape(opt_api_groups));
5049 if (opt_icarus_options)
5050 fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", json_escape(opt_icarus_options));
5051 if (opt_icarus_timing)
5052 fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", json_escape(opt_icarus_timing));
5053 fputs("\n}\n", fcfg);
5054
5055 json_escape_free();
5056}
5057
5058void zero_bestshare(void)
5059{
5060 int i;
5061
5062 best_diff = 0;
5063 memset(best_share, 0, 8);
5064 suffix_string(best_diff, best_share, 0);
5065
5066 for (i = 0; i < total_pools; i++) {
5067 struct pool *pool = pools[i];
5068 pool->best_diff = 0;
5069 }
5070}
5071
5072void zero_stats(void)
5073{
5074 int i;
5075
5076 gettimeofday(&total_tv_start, NULL((void*)0));
5077 miner_started = total_tv_start;
5078 total_mhashes_done = 0;
5079 total_getworks = 0;
5080 total_accepted = 0;
5081 total_rejected = 0;
5082 hw_errors = 0;
5083 total_stale = 0;
5084 total_discarded = 0;
5085 total_bytes_xfer = 0;
5086 new_blocks = 0;
5087 local_work = 0;
5088 total_go = 0;
5089 total_ro = 0;
5090 total_secs = 1.0;
5091 total_diff1 = 0;
5092 found_blocks = 0;
5093 total_diff_accepted = 0;
5094 total_diff_rejected = 0;
5095 total_diff_stale = 0;
5096
5097 for (i = 0; i < total_pools; i++) {
5098 struct pool *pool = pools[i];
5099
5100 pool->getwork_requested = 0;
5101 pool->accepted = 0;
5102 pool->rejected = 0;
5103 pool->solved = 0;
5104 pool->getwork_requested = 0;
5105 pool->stale_shares = 0;
5106 pool->discarded_work = 0;
5107 pool->getfail_occasions = 0;
5108 pool->remotefail_occasions = 0;
5109 pool->last_share_time = 0;
5110 pool->diff1 = 0;
5111 pool->diff_accepted = 0;
5112 pool->diff_rejected = 0;
5113 pool->diff_stale = 0;
5114 pool->last_share_diff = 0;
5115 pool->cgminer_stats.getwork_calls = 0;
5116 pool->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET99999999;
5117 pool->cgminer_stats.getwork_wait_max.tv_sec = 0;
5118 pool->cgminer_stats.getwork_wait_max.tv_usec = 0;
5119 pool->cgminer_pool_stats.getwork_calls = 0;
5120 pool->cgminer_pool_stats.getwork_attempts = 0;
5121 pool->cgminer_pool_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET99999999;
5122 pool->cgminer_pool_stats.getwork_wait_max.tv_sec = 0;
5123 pool->cgminer_pool_stats.getwork_wait_max.tv_usec = 0;
5124 pool->cgminer_pool_stats.min_diff = 0;
5125 pool->cgminer_pool_stats.max_diff = 0;
5126 pool->cgminer_pool_stats.min_diff_count = 0;
5127 pool->cgminer_pool_stats.max_diff_count = 0;
5128 pool->cgminer_pool_stats.times_sent = 0;
5129 pool->cgminer_pool_stats.bytes_sent = 0;
5130 pool->cgminer_pool_stats.net_bytes_sent = 0;
5131 pool->cgminer_pool_stats.times_received = 0;
5132 pool->cgminer_pool_stats.bytes_received = 0;
5133 pool->cgminer_pool_stats.net_bytes_received = 0;
5134 }
5135
5136 zero_bestshare();
5137
5138 mutex_lock(&hash_lock);
5139 for (i = 0; i < total_devices; ++i) {
5140 struct cgpu_info *cgpu = devices[i];
5141
5142 cgpu->total_mhashes = 0;
5143 cgpu->accepted = 0;
5144 cgpu->rejected = 0;
5145 cgpu->hw_errors = 0;
5146 cgpu->utility = 0.0;
5147 cgpu->utility_diff1 = 0;
5148 cgpu->last_share_pool_time = 0;
5149 cgpu->diff1 = 0;
5150 cgpu->diff_accepted = 0;
5151 cgpu->diff_rejected = 0;
5152 cgpu->last_share_diff = 0;
5153 cgpu->thread_fail_init_count = 0;
5154 cgpu->thread_zero_hash_count = 0;
5155 cgpu->thread_fail_queue_count = 0;
5156 cgpu->dev_sick_idle_60_count = 0;
5157 cgpu->dev_dead_idle_600_count = 0;
5158 cgpu->dev_nostart_count = 0;
5159 cgpu->dev_over_heat_count = 0;
5160 cgpu->dev_thermal_cutoff_count = 0;
5161 cgpu->dev_comms_error_count = 0;
5162 cgpu->dev_throttle_count = 0;
5163 cgpu->cgminer_stats.getwork_calls = 0;
5164 cgpu->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET99999999;
5165 cgpu->cgminer_stats.getwork_wait_max.tv_sec = 0;
5166 cgpu->cgminer_stats.getwork_wait_max.tv_usec = 0;
5167 }
5168 mutex_unlock(&hash_lock);
5169}
5170
5171#ifdef HAVE_CURSES1
5172static void display_pools(void)
5173{
5174 struct pool *pool;
5175 int selected, i, j;
5176 char input;
5177
5178 opt_loginput = true1;
5179 immedok(logwin, true1);
5180 clear_logwin();
5181updated:
5182 for (j = 0; j < total_pools; j++) {
5183 for (i = 0; i < total_pools; i++) {
5184 pool = pools[i];
5185
5186 if (pool->prio != j)
5187 continue;
5188
5189 if (pool == current_pool())
5190 wattron(logwin, A_BOLD)wattr_on(logwin, (attr_t)(((1UL) << ((13) + 8))), ((void
*)0))
;
5191 if (pool->enabled != POOL_ENABLED)
5192 wattron(logwin, A_DIM)wattr_on(logwin, (attr_t)(((1UL) << ((12) + 8))), ((void
*)0))
;
5193 wlogprint("%d: ", pool->prio);
5194 switch (pool->enabled) {
5195 case POOL_ENABLED:
5196 wlogprint("Enabled ");
5197 break;
5198 case POOL_DISABLED:
5199 wlogprint("Disabled ");
5200 break;
5201 case POOL_REJECTING:
5202 wlogprint("Rejectin ");
5203 break;
5204 }
5205 if (pool->idle)
5206 wlogprint("Dead ");
5207 else
5208 if (pool->has_stratum)
5209 wlogprint("Strtm");
5210 else
5211 if (pool->lp_url && pool->proto != pool->lp_proto)
5212 wlogprint("Mixed");
5213 else
5214 switch (pool->proto) {
5215 case PLP_GETBLOCKTEMPLATE:
5216 wlogprint(" GBT ");
5217 break;
5218 case PLP_GETWORK:
5219 wlogprint("GWork");
5220 break;
5221 default:
5222 wlogprint("Alive");
5223 }
5224 wlogprint(" Pool %d: %s User:%s\n",
5225 pool->pool_no,
5226 pool->rpc_url, pool->rpc_user);
5227 wattroff(logwin, A_BOLD | A_DIM)wattr_off(logwin, (attr_t)(((1UL) << ((13) + 8)) | ((1UL
) << ((12) + 8))), ((void*)0))
;
5228
5229 break; //for (i = 0; i < total_pools; i++)
5230 }
5231 }
5232retry:
5233 wlogprint("\nCurrent pool management strategy: %s\n",
5234 strategies[pool_strategy]);
5235 if (pool_strategy == POOL_ROTATE)
5236 wlogprint("Set to rotate every %d minutes\n", opt_rotate_period);
5237 wlogprint("[F]ailover only %s\n", opt_fail_only ? "enabled" : "disabled");
5238 wlogprint("[A]dd pool [R]emove pool [D]isable pool [E]nable pool [P]rioritize pool\n");
5239 wlogprint("[C]hange management strategy [S]witch pool [I]nformation\n");
5240 wlogprint("Or press any other key to continue\n");
5241 input = getch()my_cancellable_getch();
5242
5243 if (!strncasecmp(&input, "a", 1)) {
5244 input_pool(true1);
5245 goto updated;
5246 } else if (!strncasecmp(&input, "r", 1)) {
5247 if (total_pools <= 1) {
5248 wlogprint("Cannot remove last pool");
5249 goto retry;
5250 }
5251 selected = curses_int("Select pool number");
5252 if (selected < 0 || selected >= total_pools) {
5253 wlogprint("Invalid selection\n");
5254 goto retry;
5255 }
5256 pool = pools[selected];
5257 if (pool == current_pool())
5258 switch_pools(NULL((void*)0));
5259 if (pool == current_pool()) {
5260 wlogprint("Unable to remove pool due to activity\n");
5261 goto retry;
5262 }
5263 disable_pool(pool);
5264 remove_pool(pool);
5265 goto updated;
5266 } else if (!strncasecmp(&input, "s", 1)) {
5267 selected = curses_int("Select pool number");
5268 if (selected < 0 || selected >= total_pools) {
5269 wlogprint("Invalid selection\n");
5270 goto retry;
5271 }
5272 pool = pools[selected];
5273 enable_pool(pool);
5274 switch_pools(pool);
5275 goto updated;
5276 } else if (!strncasecmp(&input, "d", 1)) {
5277 if (enabled_pools <= 1) {
5278 wlogprint("Cannot disable last pool");
5279 goto retry;
5280 }
5281 selected = curses_int("Select pool number");
5282 if (selected < 0 || selected >= total_pools) {
5283 wlogprint("Invalid selection\n");
5284 goto retry;
5285 }
5286 pool = pools[selected];
5287 disable_pool(pool);
5288 if (pool == current_pool())
5289 switch_pools(NULL((void*)0));
5290 goto updated;
5291 } else if (!strncasecmp(&input, "e", 1)) {
5292 selected = curses_int("Select pool number");
5293 if (selected < 0 || selected >= total_pools) {
5294 wlogprint("Invalid selection\n");
5295 goto retry;
5296 }
5297 pool = pools[selected];
5298 enable_pool(pool);
5299 if (pool->prio < current_pool()->prio)
5300 switch_pools(pool);
5301 goto updated;
5302 } else if (!strncasecmp(&input, "c", 1)) {
5303 for (i = 0; i <= TOP_STRATEGY(POOL_BALANCE); i++)
5304 wlogprint("%d: %s\n", i, strategies[i]);
5305 selected = curses_int("Select strategy number type");
5306 if (selected < 0 || selected > TOP_STRATEGY(POOL_BALANCE)) {
5307 wlogprint("Invalid selection\n");
5308 goto retry;
5309 }
5310 if (selected == POOL_ROTATE) {
5311 opt_rotate_period = curses_int("Select interval in minutes");
5312
5313 if (opt_rotate_period < 0 || opt_rotate_period > 9999) {
5314 opt_rotate_period = 0;
5315 wlogprint("Invalid selection\n");
5316 goto retry;
5317 }
5318 }
5319 pool_strategy = selected;
5320 switch_pools(NULL((void*)0));
5321 goto updated;
5322 } else if (!strncasecmp(&input, "i", 1)) {
5323 selected = curses_int("Select pool number");
5324 if (selected < 0 || selected >= total_pools) {
5325 wlogprint("Invalid selection\n");
5326 goto retry;
5327 }
5328 pool = pools[selected];
5329 display_pool_summary(pool);
5330 goto retry;
5331 } else if (!strncasecmp(&input, "f", 1)) {
5332 opt_fail_only ^= true1;
5333 goto updated;
5334 } else if (!strncasecmp(&input, "p", 1)) {
5335 char *prilist = curses_input("Enter new pool priority (comma separated list)");
5336 int res = prioritize_pools(prilist, &i);
5337 free(prilist);
5338 switch (res) {
5339 case MSG_NOPOOL:
5340 wlogprint("No pools\n");
5341 goto retry;
5342 case MSG_MISPID:
5343 wlogprint("Missing pool id parameter\n");
5344 goto retry;
5345 case MSG_INVPID:
5346 wlogprint("Invalid pool id %d - range is 0 - %d\n", i, total_pools - 1);
5347 goto retry;
5348 case MSG_DUPPID:
5349 wlogprint("Duplicate pool specified %d\n", i);
5350 goto retry;
5351 case MSG_POOLPRIO:
5352 default:
5353 goto updated;
5354 }
5355 } else
5356 clear_logwin();
5357
5358 immedok(logwin, false0);
5359 opt_loginput = false0;
5360}
5361
5362static const char *summary_detail_level_str(void)
5363{
5364 if (opt_compact)
5365 return "compact";
5366 if (opt_show_procs)
5367 return "processors";
5368 return "devices";
5369}
5370
5371static void display_options(void)
5372{
5373 int selected;
5374 char input;
5375
5376 opt_loginput = true1;
5377 immedok(logwin, true1);
5378 clear_logwin();
5379retry:
5380 wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n");
5381 wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n"
5382 "[R]PC debug:%s\n[W]orkTime details:%s\nsu[M]mary detail level:%s\n"
5383 "[L]og interval:%d\n[Z]ero statistics\n",
5384 opt_debug_console ? "on" : "off",
5385 want_per_device_stats? "on" : "off",
5386 opt_quiet ? "on" : "off",
5387 opt_log_output ? "on" : "off",
5388 opt_protocol ? "on" : "off",
5389 opt_worktime ? "on" : "off",
5390 summary_detail_level_str(),
5391 opt_log_interval);
5392 wlogprint("Select an option or any other key to return\n");
5393 input = getch()my_cancellable_getch();
5394 if (!strncasecmp(&input, "q", 1)) {
5395 opt_quiet ^= true1;
5396 wlogprint("Quiet mode %s\n", opt_quiet ? "enabled" : "disabled");
5397 goto retry;
5398 } else if (!strncasecmp(&input, "v", 1)) {
5399 opt_log_output ^= true1;
5400 if (opt_log_output)
5401 opt_quiet = false0;
5402 wlogprint("Verbose mode %s\n", opt_log_output ? "enabled" : "disabled");
5403 goto retry;
5404 } else if (!strncasecmp(&input, "n", 1)) {
5405 opt_log_output = false0;
5406 opt_debug_console = false0;
5407 opt_quiet = false0;
5408 opt_protocol = false0;
5409 opt_compact = false0;
5410 opt_show_procs = false0;
5411 devsummaryYOffset = 0;
5412 want_per_device_stats = false0;
5413 wlogprint("Output mode reset to normal\n");
5414 switch_compact();
5415 goto retry;
5416 } else if (!strncasecmp(&input, "d", 1)) {
5417 opt_debug = true1;
5418 opt_debug_console ^= true1;
5419 opt_log_output = opt_debug_console;
5420 if (opt_debug_console)
5421 opt_quiet = false0;
5422 wlogprint("Debug mode %s\n", opt_debug_console ? "enabled" : "disabled");
5423 goto retry;
5424 } else if (!strncasecmp(&input, "m", 1)) {
5425 if (opt_compact)
5426 opt_compact = false0;
5427 else
5428 if (!opt_show_procs)
5429 opt_show_procs = true1;
5430 else
5431 {
5432 opt_compact = true1;
5433 opt_show_procs = false0;
5434 devsummaryYOffset = 0;
5435 }
5436 wlogprint("su[M]mary detail level changed to: %s\n", summary_detail_level_str());
5437 switch_compact();
5438 goto retry;
5439 } else if (!strncasecmp(&input, "p", 1)) {
5440 want_per_device_stats ^= true1;
5441 opt_log_output = want_per_device_stats;
5442 wlogprint("Per-device stats %s\n", want_per_device_stats ? "enabled" : "disabled");
5443 goto retry;
5444 } else if (!strncasecmp(&input, "r", 1)) {
5445 opt_protocol ^= true1;
5446 if (opt_protocol)
5447 opt_quiet = false0;
5448 wlogprint("RPC protocol debugging %s\n", opt_protocol ? "enabled" : "disabled");
5449 goto retry;
5450 } else if (!strncasecmp(&input, "c", 1))
5451 clear_logwin();
5452 else if (!strncasecmp(&input, "l", 1)) {
5453 selected = curses_int("Interval in seconds");
5454 if (selected < 0 || selected > 9999) {
5455 wlogprint("Invalid selection\n");
5456 goto retry;
5457 }
5458 opt_log_interval = selected;
5459 wlogprint("Log interval set to %d seconds\n", opt_log_interval);
5460 goto retry;
5461 } else if (!strncasecmp(&input, "s", 1)) {
5462 opt_realquiet = true1;
5463 } else if (!strncasecmp(&input, "w", 1)) {
5464 opt_worktime ^= true1;
5465 wlogprint("WorkTime details %s\n", opt_worktime ? "enabled" : "disabled");
5466 goto retry;
5467 } else if (!strncasecmp(&input, "z", 1)) {
5468 zero_stats();
5469 goto retry;
5470 } else
5471 clear_logwin();
5472
5473 immedok(logwin, false0);
5474 opt_loginput = false0;
5475}
5476#endif
5477
5478void default_save_file(char *filename)
5479{
5480#if defined(unix1)
5481 if (getenv("HOME") && *getenv("HOME")) {
5482 strcpy(filename, getenv("HOME"));
5483 strcat(filename, "/");
5484 }
5485 else
5486 strcpy(filename, "");
5487 strcat(filename, ".bfgminer/");
5488 mkdir(filename, 0777);
5489#else
5490 strcpy(filename, "");
5491#endif
5492 strcat(filename, def_conf);
5493}
5494
5495#ifdef HAVE_CURSES1
5496static void set_options(void)
5497{
5498 int selected;
5499 char input;
5500
5501 opt_loginput = true1;
5502 immedok(logwin, true1);
5503 clear_logwin();
5504retry:
5505 wlogprint("\n[L]ongpoll: %s\n", want_longpoll ? "On" : "Off");
5506 wlogprint("[Q]ueue: %d\n[S]cantime: %d\n[E]xpiry: %d\n[R]etries: %d\n"
5507 "[W]rite config file\n[B]FGMiner restart\n",
5508 opt_queue, opt_scantime, opt_expiry, opt_retries);
5509 wlogprint("Select an option or any other key to return\n");
5510 input = getch()my_cancellable_getch();
5511
5512 if (!strncasecmp(&input, "q", 1)) {
5513 selected = curses_int("Extra work items to queue");
5514 if (selected < 0 || selected > 9999) {
5515 wlogprint("Invalid selection\n");
5516 goto retry;
5517 }
5518 opt_queue = selected;
5519 goto retry;
5520 } else if (!strncasecmp(&input, "l", 1)) {
5521 if (want_longpoll)
5522 stop_longpoll();
5523 else
5524 start_longpoll();
5525 applog(LOG_WARNING4, "Longpoll %s", want_longpoll ? "enabled" : "disabled");
5526 goto retry;
5527 } else if (!strncasecmp(&input, "s", 1)) {
5528 selected = curses_int("Set scantime in seconds");
5529 if (selected < 0 || selected > 9999) {
5530 wlogprint("Invalid selection\n");
5531 goto retry;
5532 }
5533 opt_scantime = selected;
5534 goto retry;
5535 } else if (!strncasecmp(&input, "e", 1)) {
5536 selected = curses_int("Set expiry time in seconds");
5537 if (selected < 0 || selected > 9999) {
5538 wlogprint("Invalid selection\n");
5539 goto retry;
5540 }
5541 opt_expiry = selected;
5542 goto retry;
5543 } else if (!strncasecmp(&input, "r", 1)) {
5544 selected = curses_int("Retries before failing (-1 infinite)");
5545 if (selected < -1 || selected > 9999) {
5546 wlogprint("Invalid selection\n");
5547 goto retry;
5548 }
5549 opt_retries = selected;
5550 goto retry;
5551 } else if (!strncasecmp(&input, "w", 1)) {
5552 FILE *fcfg;
5553 char *str, filename[PATH_MAX4096], prompt[PATH_MAX4096 + 50];
5554
5555 default_save_file(filename);
5556 sprintf(prompt, "Config filename to write (Enter for default) [%s]", filename);
5557 str = curses_input(prompt);
5558 if (strcmp(str, "-1")) {
5559 struct stat statbuf;
5560
5561 strcpy(filename, str);
5562 free(str);
5563 if (!stat(filename, &statbuf)) {
5564 wlogprint("File exists, overwrite?\n");
5565 input = getch()my_cancellable_getch();
5566 if (strncasecmp(&input, "y", 1))
5567 goto retry;
5568 }
5569 }
5570 else
5571 free(str);
5572 fcfg = fopen(filename, "w");
5573 if (!fcfg) {
5574 wlogprint("Cannot open or create file\n");
5575 goto retry;
5576 }
5577 write_config(fcfg);
5578 fclose(fcfg);
5579 goto retry;
5580
5581 } else if (!strncasecmp(&input, "b", 1)) {
5582 wlogprint("Are you sure?\n");
5583 input = getch()my_cancellable_getch();
5584 if (!strncasecmp(&input, "y", 1))
5585 app_restart();
5586 else
5587 clear_logwin();
5588 } else
5589 clear_logwin();
5590
5591 immedok(logwin, false0);
5592 opt_loginput = false0;
5593}
5594
5595static void *input_thread(void __maybe_unused__attribute__((unused)) *userdata)
5596{
5597 RenameThread("input");
5598
5599 if (!curses_active)
5600 return NULL((void*)0);
5601
5602 while (1) {
5603 int input;
5604
5605 input = getch()my_cancellable_getch();
5606 switch (input) {
5607 case 'q': case 'Q':
5608 kill_work();
5609 return NULL((void*)0);
5610 case 'd': case 'D':
5611 display_options();
5612 break;
5613 case 'p': case 'P':
5614 display_pools();
5615 break;
5616 case 's': case 'S':
5617 set_options();
5618 break;
5619 case 'g': case 'G':
5620 if (have_opencl)
5621 manage_gpu();
5622 break;
5623#ifdef HAVE_CURSES1
5624 case KEY_DOWN0402:
5625 if (devsummaryYOffset < -(total_lines + devcursor - statusy))
5626 break;
5627 devsummaryYOffset -= 2;
5628 case KEY_UP0403:
5629 if (devsummaryYOffset == 0)
5630 break;
5631 ++devsummaryYOffset;
5632 if (curses_active_locked()) {
5633 int i;
5634 for (i = 0; i < mining_threads; i++)
5635 curses_print_devstatus(i);
5636 touchwin(statuswin)wtouchln((statuswin), 0, ((statuswin) ? ((statuswin)->_maxy
+ 1) : (-1)), 1)
;
5637 wrefresh(statuswin);
5638 unlock_curses();
5639 }
5640 break;
5641#endif
5642 }
5643 if (opt_realquiet) {
5644 disable_curses();
5645 break;
5646 }
5647 }
5648
5649 return NULL((void*)0);
5650}
5651#endif
5652
5653static void *api_thread(void *userdata)
5654{
5655 struct thr_info *mythr = userdata;
5656
5657 pthread_detach(pthread_self());
5658 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUSPTHREAD_CANCEL_ASYNCHRONOUS, NULL((void*)0));
5659
5660 RenameThread("rpc");
5661
5662 api(api_thr_id);
5663
5664 PTH(mythr)((mythr)->pth) = 0L;
5665
5666 return NULL((void*)0);
5667}
5668
5669void thread_reportin(struct thr_info *thr)
5670{
5671 gettimeofday(&thr->last, NULL((void*)0));
5672 thr->cgpu->status = LIFE_WELL;
5673 thr->getwork = 0;
5674 thr->cgpu->device_last_well = time(NULL((void*)0));
5675}
5676
5677void thread_reportout(struct thr_info *thr)
5678{
5679 thr->getwork = time(NULL((void*)0));
5680}
5681
5682static void hashmeter(int thr_id, struct timeval *diff,
5683 uint64_t hashes_done)
5684{
5685 struct timeval temp_tv_end, total_diff;
5686 double secs;
5687 double local_secs;
5688 double utility;
5689 static double local_mhashes_done = 0;
5690 static double rolling = 0;
5691 double local_mhashes = (double)hashes_done / 1000000.0;
5692 bool_Bool showlog = false0;
5693 char cHr[h2bs_fmt_size[H2B_NOUNIT]], aHr[h2bs_fmt_size[H2B_NOUNIT]], uHr[h2bs_fmt_size[H2B_SPACED]];
5694
5695 /* Update the last time this thread reported in */
5696 if (thr_id >= 0) {
5697 gettimeofday(&thr_info[thr_id].last, NULL((void*)0));
5698 thr_info[thr_id].cgpu->device_last_well = time(NULL((void*)0));
5699 }
5700
5701 secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
5702
5703 /* So we can call hashmeter from a non worker thread */
5704 if (thr_id >= 0) {
5705 struct thr_info *thr = &thr_info[thr_id];
5706 struct cgpu_info *cgpu = thr_info[thr_id].cgpu;
5707 int threadobj = cgpu->threads ?: 1;
5708 double thread_rolling = 0.0;
5709 int i;
5710
5711 applog(LOG_DEBUG7, "[thread %d: %"PRIu64"ll" "u"" hashes, %.1f khash/sec]",
5712 thr_id, hashes_done, hashes_done / 1000 / secs);
5713
5714 /* Rolling average for each thread and each device */
5715 decay_time(&thr->rolling, local_mhashes / secs);
5716 for (i = 0; i < threadobj; i++)
5717 thread_rolling += cgpu->thr[i]->rolling;
5718
5719 mutex_lock(&hash_lock);
5720 decay_time(&cgpu->rolling, thread_rolling);
5721 cgpu->total_mhashes += local_mhashes;
5722 mutex_unlock(&hash_lock);
5723
5724 // If needed, output detailed, per-device stats
5725 if (want_per_device_stats) {
5726 struct timeval now;
5727 struct timeval elapsed;
5728 struct timeval *last_msg_tv = opt_show_procs ? &thr->cgpu->last_message_tv : &thr->cgpu->device->last_message_tv;
5729
5730 gettimeofday(&now, NULL((void*)0));
5731 timersub(&now, last_msg_tv, &elapsed)do { (&elapsed)->tv_sec = (&now)->tv_sec - (last_msg_tv
)->tv_sec; (&elapsed)->tv_usec = (&now)->tv_usec
- (last_msg_tv)->tv_usec; if ((&elapsed)->tv_usec <
0) { --(&elapsed)->tv_sec; (&elapsed)->tv_usec
+= 1000000; } } while (0)
;
5732 if (opt_log_interval <= elapsed.tv_sec) {
5733 struct cgpu_info *cgpu = thr->cgpu;
5734 char logline[255];
5735
5736 *last_msg_tv = now;
5737
5738 get_statline(logline, cgpu)get_statline2(logline, cgpu, 0);
5739 if (!curses_active) {
5740 printf("%s \r", logline);
5741 fflush(stdoutstdout);
5742 } else
5743 applog(LOG_INFO6, "%s", logline);
5744 }
5745 }
5746 }
5747
5748 /* Totals are updated by all threads so can race without locking */
5749 mutex_lock(&hash_lock);
5750 gettimeofday(&temp_tv_end, NULL((void*)0));
5751 timersub(&temp_tv_end, &total_tv_end, &total_diff)do { (&total_diff)->tv_sec = (&temp_tv_end)->tv_sec
- (&total_tv_end)->tv_sec; (&total_diff)->tv_usec
= (&temp_tv_end)->tv_usec - (&total_tv_end)->tv_usec
; if ((&total_diff)->tv_usec < 0) { --(&total_diff
)->tv_sec; (&total_diff)->tv_usec += 1000000; } } while
(0)
;
5752
5753 total_mhashes_done += local_mhashes;
5754 local_mhashes_done += local_mhashes;
5755 if (total_diff.tv_sec < opt_log_interval)
5756 /* Only update the total every opt_log_interval seconds */
5757 goto out_unlock;
5758 showlog = true1;
5759 gettimeofday(&total_tv_end, NULL((void*)0));
5760
5761 local_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0);
5762 decay_time(&rolling, local_mhashes_done / local_secs);
5763 global_hashrate = roundl(rolling)(long double)((long long)((rolling==0)?0.0:((rolling)+((rolling
)>0)?0.5:-0.5)))
* 1000000;
5764
5765 timersub(&total_tv_end, &total_tv_start, &total_diff)do { (&total_diff)->tv_sec = (&total_tv_end)->tv_sec
- (&total_tv_start)->tv_sec; (&total_diff)->tv_usec
= (&total_tv_end)->tv_usec - (&total_tv_start)->
tv_usec; if ((&total_diff)->tv_usec < 0) { --(&
total_diff)->tv_sec; (&total_diff)->tv_usec += 1000000
; } } while (0)
;
5766 total_secs = (double)total_diff.tv_sec +
5767 ((double)total_diff.tv_usec / 1000000.0);
5768
5769 utility = total_accepted / total_secs * 60;
5770
5771 ti_hashrate_bufstr(
5772 (char*[]){cHr, aHr, uHr},
5773 1e6*rolling,
5774 1e6*total_mhashes_done / total_secs,
5775 utility_to_hashrate(total_diff_accepted / (total_secs ?: 1) * 60),
5776 H2B_SPACED);
5777
5778 sprintf(statusline, "%s%ds:%s avg:%s u:%s | A:%d R:%d S:%d HW:%d U:%.1f/m BS:%s",
5779 want_per_device_stats ? "ALL " : "",
5780 opt_log_interval,
5781 cHr, aHr,
5782 uHr,
5783 total_accepted, total_rejected, total_stale,
5784 hw_errors,
5785 utility,
5786 best_share);
5787
5788
5789 local_mhashes_done = 0;
5790out_unlock:
5791 mutex_unlock(&hash_lock);
5792 if (showlog) {
5793 if (!curses_active) {
5794 printf("%s \r", statusline);
5795 fflush(stdoutstdout);
5796 } else
5797 applog(LOG_INFO6, "%s", statusline);
5798 }
5799}
5800
5801void hashmeter2(struct thr_info *thr)
5802{
5803 struct timeval tv_now, tv_elapsed;
5804
5805 timerclear(&thr->tv_hashes_done)((&thr->tv_hashes_done)->tv_sec = (&thr->tv_hashes_done
)->tv_usec = 0)
;
5806
5807 gettimeofday(&tv_now, NULL((void*)0));
5808 timersub(&tv_now, &thr->tv_lastupdate, &tv_elapsed)do { (&tv_elapsed)->tv_sec = (&tv_now)->tv_sec -
(&thr->tv_lastupdate)->tv_sec; (&tv_elapsed)->
tv_usec = (&tv_now)->tv_usec - (&thr->tv_lastupdate
)->tv_usec; if ((&tv_elapsed)->tv_usec < 0) { --
(&tv_elapsed)->tv_sec; (&tv_elapsed)->tv_usec +=
1000000; } } while (0)
;
5809 if (tv_elapsed.tv_sec >= opt_log_interval) {
5810 hashmeter(thr->id, &tv_elapsed, thr->hashes_done);
5811 thr->hashes_done = 0;
5812 thr->tv_lastupdate = tv_now;
5813 }
5814}
5815
5816static void stratum_share_result(json_t *val, json_t *res_val, json_t *err_val,
5817 struct stratum_share *sshare)
5818{
5819 struct work *work = sshare->work;
5820
5821 share_result(val, res_val, err_val, work, false0, "");
5822}
5823
5824/* Parses stratum json responses and tries to find the id that the request
5825 * matched to and treat it accordingly. */
5826bool_Bool parse_stratum_response(struct pool *pool, char *s)
5827{
5828 json_t *val = NULL((void*)0), *err_val, *res_val, *id_val;
5829 struct stratum_share *sshare;
5830 json_error_t err;
5831 bool_Bool ret = false0;
5832 int id;
5833
5834 val = JSON_LOADS(s, &err)json_loads((s), 0, (&err));
5835 if (!val) {
5836 applog(LOG_INFO6, "JSON decode failed(%d): %s", err.line, err.text);
5837 goto out;
5838 }
5839
5840 res_val = json_object_get(val, "result");
5841 err_val = json_object_get(val, "error");
5842 id_val = json_object_get(val, "id");
5843
5844 if (json_is_null(id_val)(id_val && ((id_val)->type) == JSON_NULL) || !id_val) {
5845 char *ss;
5846
5847 if (err_val)
5848 ss = json_dumps(err_val, JSON_INDENT(3)(3 & 0x1F));
5849 else
5850 ss = strdup("(unknown reason)");
5851
5852 applog(LOG_INFO6, "JSON-RPC non method decode failed: %s", ss);
5853
5854 free(ss);
5855
5856 goto out;
5857 }
5858
5859 if (!json_is_integer(id_val)(id_val && ((id_val)->type) == JSON_INTEGER)) {
5860 if (json_is_string(id_val)(id_val && ((id_val)->type) == JSON_STRING)
5861 && !strncmp(json_string_value(id_val), "txlist", 6)
5862 && !strcmp(json_string_value(id_val) + 6, pool->swork.job_id)
5863 && json_is_array(res_val)(res_val && ((res_val)->type) == JSON_ARRAY)) {
5864 // Check that the transactions actually hash to the merkle links
5865 {
5866 unsigned maxtx = 1 << pool->swork.merkles;
5867 unsigned mintx = maxtx >> 1;
5868 --maxtx;
5869 unsigned acttx = (unsigned)json_array_size(res_val);
5870 if (acttx < mintx || acttx > maxtx) {
5871 applog(LOG_WARNING4, "Pool %u is sending mismatched block contents to us (%u is not %u-%u)",
5872 pool->pool_no, acttx, mintx, maxtx);
5873 goto fishy;
5874 }
5875 // TODO: Check hashes match actual merkle links
5876 }
5877
5878 if (pool->swork.opaque) {
5879 pool->swork.opaque = false0;
5880 applog(LOG_NOTICE5, "Pool %u now providing block contents to us",
5881 pool->pool_no);
5882 }
5883 pool->swork.transparency_time = (time_t)-1;
5884
5885fishy:
5886 ret = true1;
5887 }
5888
5889 goto out;
5890 }
5891
5892 id = json_integer_value(id_val);
5893 mutex_lock(&sshare_lock);
5894 HASH_FIND_INT(stratum_shares, &id, sshare)do { unsigned _hf_bkt,_hf_hashv; sshare=((void*)0); if (stratum_shares
) { do { unsigned _hj_i,_hj_j,_hj_k; char *_hj_key=(char*)(&
id); _hf_hashv = 0xfeedbeef; _hj_i = _hj_j = 0x9e3779b9; _hj_k
= (unsigned)sizeof(int); while (_hj_k >= 12) { _hj_i += (
_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) + ( (unsigned
)_hj_key[2] << 16 ) + ( (unsigned)_hj_key[3] << 24
) ); _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8
) + ( (unsigned)_hj_key[6] << 16 ) + ( (unsigned)_hj_key
[7] << 24 ) ); _hf_hashv += (_hj_key[8] + ( (unsigned)_hj_key
[9] << 8 ) + ( (unsigned)_hj_key[10] << 16 ) + ( (
unsigned)_hj_key[11] << 24 ) ); do { _hj_i -= _hj_j; _hj_i
-= _hf_hashv; _hj_i ^= ( _hf_hashv >> 13 ); _hj_j -= _hf_hashv
; _hj_j -= _hj_i; _hj_j ^= ( _hj_i << 8 ); _hf_hashv -=
_hj_i; _hf_hashv -= _hj_j; _hf_hashv ^= ( _hj_j >> 13 )
; _hj_i -= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv >>
12 ); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
16 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv ^= (
_hj_j >> 5 ); _hj_i -= _hj_j; _hj_i -= _hf_hashv; _hj_i
^= ( _hf_hashv >> 3 ); _hj_j -= _hf_hashv; _hj_j -= _hj_i
; _hj_j ^= ( _hj_i << 10 ); _hf_hashv -= _hj_i; _hf_hashv
-= _hj_j; _hf_hashv ^= ( _hj_j >> 15 ); } while (0); _hj_key
+= 12; _hj_k -= 12; } _hf_hashv += sizeof(int); switch ( _hj_k
) { case 11: _hf_hashv += ( (unsigned)_hj_key[10] << 24
); case 10: _hf_hashv += ( (unsigned)_hj_key[9] << 16 )
; case 9: _hf_hashv += ( (unsigned)_hj_key[8] << 8 ); case
8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); case 7: _hj_j
+= ( (unsigned)_hj_key[6] << 16 ); case 6: _hj_j += ( (
unsigned)_hj_key[5] << 8 ); case 5: _hj_j += _hj_key[4]
; case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); case
3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); case 2: _hj_i
+= ( (unsigned)_hj_key[1] << 8 ); case 1: _hj_i += _hj_key
[0]; } do { _hj_i -= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv
>> 13 ); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= (
_hj_i << 8 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv
^= ( _hj_j >> 13 ); _hj_i -= _hj_j; _hj_i -= _hf_hashv
; _hj_i ^= ( _hf_hashv >> 12 ); _hj_j -= _hf_hashv; _hj_j
-= _hj_i; _hj_j ^= ( _hj_i << 16 ); _hf_hashv -= _hj_i
; _hf_hashv -= _hj_j; _hf_hashv ^= ( _hj_j >> 5 ); _hj_i
-= _hj_j; _hj_i -= _hf_hashv; _hj_i ^= ( _hf_hashv >> 3
); _hj_j -= _hf_hashv; _hj_j -= _hj_i; _hj_j ^= ( _hj_i <<
10 ); _hf_hashv -= _hj_i; _hf_hashv -= _hj_j; _hf_hashv ^= (
_hj_j >> 15 ); } while (0); _hf_bkt = _hf_hashv & (
(stratum_shares)->hh.tbl->num_buckets-1); } while(0); if
((1)) { do { if ((stratum_shares)->hh.tbl->buckets[ _hf_bkt
].hh_head) do { (sshare) = (__typeof(sshare))(((void*)(((char
*)((stratum_shares)->hh.tbl->buckets[ _hf_bkt ].hh_head
)) - (((stratum_shares)->hh.tbl)->hho)))); } while(0); else
sshare=((void*)0); while (sshare) { if ((sshare)->hh.keylen
== sizeof(int)) { if ((memcmp((sshare)->hh.key,&id,sizeof
(int))) == 0) break; } if ((sshare)->hh.hh_next) do { (sshare
) = (__typeof(sshare))(((void*)(((char*)((sshare)->hh.hh_next
)) - (((stratum_shares)->hh.tbl)->hho)))); } while(0); else
sshare = ((void*)0); } } while(0); } } } while (0)
;
5895 if (sshare)
5896 HASH_DEL(stratum_shares, sshare)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((sshare)->hh.prev == ((void*)0)) && ((sshare)->
hh.next == ((void*)0)) ) { free((stratum_shares)->hh.tbl->
buckets); ; free((stratum_shares)->hh.tbl); stratum_shares
= ((void*)0); } else { _hd_hh_del = &((sshare)->hh); if
((sshare) == ((void*)(((char*)((stratum_shares)->hh.tbl->
tail)) - (((stratum_shares)->hh.tbl)->hho)))) { (stratum_shares
)->hh.tbl->tail = (UT_hash_handle*)((char*)((sshare)->
hh.prev) + (stratum_shares)->hh.tbl->hho); } if ((sshare
)->hh.prev) { ((UT_hash_handle*)((char*)((sshare)->hh.prev
) + (stratum_shares)->hh.tbl->hho))->next = (sshare)
->hh.next; } else { do { (stratum_shares) = (__typeof(stratum_shares
))((sshare)->hh.next); } while(0); } if (_hd_hh_del->next
) { ((UT_hash_handle*)((char*)_hd_hh_del->next + (stratum_shares
)->hh.tbl->hho))->prev = _hd_hh_del->prev; } do {
_hd_bkt = ((_hd_hh_del->hashv) & (((stratum_shares)->
hh.tbl->num_buckets) - 1)); } while(0); ((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).count--; if (((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del) { ((stratum_shares
)->hh.tbl->buckets[_hd_bkt]).hh_head = _hd_hh_del->hh_next
; } if (_hd_hh_del->hh_prev) { _hd_hh_del->hh_prev->
hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del->hh_next
) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del->hh_prev
; }; (stratum_shares)->hh.tbl->num_items--; } ; } while
(0)
;
5897 mutex_unlock(&sshare_lock);
5898 if (!sshare) {
5899 if (json_is_true(res_val)(res_val && ((res_val)->type) == JSON_TRUE))
5900 applog(LOG_NOTICE5, "Accepted untracked stratum share from pool %d", pool->pool_no);
5901 else
5902 applog(LOG_NOTICE5, "Rejected untracked stratum share from pool %d", pool->pool_no);
5903 goto out;
5904 }
5905 else {
5906 mutex_lock(&submitting_lock);
5907 --total_submitting;
5908 mutex_unlock(&submitting_lock);
5909 }
5910 stratum_share_result(val, res_val, err_val, sshare);
5911 free_work(sshare->work);
5912 free(sshare);
5913
5914 ret = true1;
5915out:
5916 if (val)
5917 json_decref(val);
5918
5919 return ret;
5920}
5921
5922static void shutdown_stratum(struct pool *pool)
5923{
5924 // Shut down Stratum as if we never had it
5925 pool->stratum_active = false0;
5926 pool->stratum_auth = false0;
5927 pool->has_stratum = false0;
5928 shutdown(pool->sock, SHUT_RDWRSHUT_RDWR);
5929 free(pool->stratum_url);
5930 if (pool->sockaddr_url == pool->stratum_url)
5931 pool->sockaddr_url = NULL((void*)0);
5932 pool->stratum_url = NULL((void*)0);
5933}
5934
5935void clear_stratum_shares(struct pool *pool)
5936{
5937 struct stratum_share *sshare, *tmpshare;
5938 struct work *work;
5939 int cleared = 0;
5940 double diff_stale = 0;
5941
5942 mutex_lock(&sshare_lock);
5943 HASH_ITER(hh, stratum_shares, sshare, tmpshare)for((sshare)=(stratum_shares),(tmpshare)=(__typeof(sshare))((
stratum_shares)?(stratum_shares)->hh.next:((void*)0)); sshare
; (sshare)=(tmpshare),(tmpshare)=(__typeof(sshare))((tmpshare
)?(tmpshare)->hh.next:((void*)0)))
{
5944 if (sshare->work->pool == pool) {
5945 HASH_DEL(stratum_shares, sshare)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((sshare)->hh.prev == ((void*)0)) && ((sshare)->
hh.next == ((void*)0)) ) { free((stratum_shares)->hh.tbl->
buckets); ; free((stratum_shares)->hh.tbl); stratum_shares
= ((void*)0); } else { _hd_hh_del = &((sshare)->hh); if
((sshare) == ((void*)(((char*)((stratum_shares)->hh.tbl->
tail)) - (((stratum_shares)->hh.tbl)->hho)))) { (stratum_shares
)->hh.tbl->tail = (UT_hash_handle*)((char*)((sshare)->
hh.prev) + (stratum_shares)->hh.tbl->hho); } if ((sshare
)->hh.prev) { ((UT_hash_handle*)((char*)((sshare)->hh.prev
) + (stratum_shares)->hh.tbl->hho))->next = (sshare)
->hh.next; } else { do { (stratum_shares) = (__typeof(stratum_shares
))((sshare)->hh.next); } while(0); } if (_hd_hh_del->next
) { ((UT_hash_handle*)((char*)_hd_hh_del->next + (stratum_shares
)->hh.tbl->hho))->prev = _hd_hh_del->prev; } do {
_hd_bkt = ((_hd_hh_del->hashv) & (((stratum_shares)->
hh.tbl->num_buckets) - 1)); } while(0); ((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).count--; if (((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del) { ((stratum_shares
)->hh.tbl->buckets[_hd_bkt]).hh_head = _hd_hh_del->hh_next
; } if (_hd_hh_del->hh_prev) { _hd_hh_del->hh_prev->
hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del->hh_next
) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del->hh_prev
; }; (stratum_shares)->hh.tbl->num_items--; } ; } while
(0)
;
5946
5947 work = sshare->work;
5948 sharelog("disconnect", work);
5949 diff_stale += work->work_difficulty;
5950
5951 free_work(sshare->work);
5952 free(sshare);
5953 cleared++;
5954 }
5955 }
5956 mutex_unlock(&sshare_lock);
5957
5958 if (cleared) {
5959 applog(LOG_WARNING4, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no);
5960 mutex_lock(&stats_lock);
5961 pool->stale_shares += cleared;
5962 total_stale += cleared;
5963 total_diff_stale += diff_stale;
5964 pool->diff_stale += diff_stale;
5965 mutex_unlock(&stats_lock);
5966
5967 mutex_lock(&submitting_lock);
5968 total_submitting -= cleared;
5969 mutex_unlock(&submitting_lock);
5970 }
5971}
5972
5973static void resubmit_stratum_shares(struct pool *pool)
5974{
5975 struct stratum_share *sshare, *tmpshare;
5976 struct work *work;
5977 unsigned resubmitted = 0;
5978
5979 mutex_lock(&sshare_lock);
5980 mutex_lock(&submitting_lock);
5981 HASH_ITER(hh, stratum_shares, sshare, tmpshare)for((sshare)=(stratum_shares),(tmpshare)=(__typeof(sshare))((
stratum_shares)?(stratum_shares)->hh.next:((void*)0)); sshare
; (sshare)=(tmpshare),(tmpshare)=(__typeof(sshare))((tmpshare
)?(tmpshare)->hh.next:((void*)0)))
{
5982 if (sshare->work->pool != pool)
5983 continue;
5984
5985 HASH_DEL(stratum_shares, sshare)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((sshare)->hh.prev == ((void*)0)) && ((sshare)->
hh.next == ((void*)0)) ) { free((stratum_shares)->hh.tbl->
buckets); ; free((stratum_shares)->hh.tbl); stratum_shares
= ((void*)0); } else { _hd_hh_del = &((sshare)->hh); if
((sshare) == ((void*)(((char*)((stratum_shares)->hh.tbl->
tail)) - (((stratum_shares)->hh.tbl)->hho)))) { (stratum_shares
)->hh.tbl->tail = (UT_hash_handle*)((char*)((sshare)->
hh.prev) + (stratum_shares)->hh.tbl->hho); } if ((sshare
)->hh.prev) { ((UT_hash_handle*)((char*)((sshare)->hh.prev
) + (stratum_shares)->hh.tbl->hho))->next = (sshare)
->hh.next; } else { do { (stratum_shares) = (__typeof(stratum_shares
))((sshare)->hh.next); } while(0); } if (_hd_hh_del->next
) { ((UT_hash_handle*)((char*)_hd_hh_del->next + (stratum_shares
)->hh.tbl->hho))->prev = _hd_hh_del->prev; } do {
_hd_bkt = ((_hd_hh_del->hashv) & (((stratum_shares)->
hh.tbl->num_buckets) - 1)); } while(0); ((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).count--; if (((stratum_shares)->
hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del) { ((stratum_shares
)->hh.tbl->buckets[_hd_bkt]).hh_head = _hd_hh_del->hh_next
; } if (_hd_hh_del->hh_prev) { _hd_hh_del->hh_prev->
hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del->hh_next
) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del->hh_prev
; }; (stratum_shares)->hh.tbl->num_items--; } ; } while
(0)
;
5986
5987 work = sshare->work;
5988 list_add_tail(&work->list, &submit_waiting);
5989
5990 free(sshare);
5991 ++resubmitted;
5992 }
5993 mutex_unlock(&submitting_lock);
5994 mutex_unlock(&sshare_lock);
5995
5996 if (resubmitted) {
5997 notifier_wake(submit_waiting_notifier);
5998 applog(LOG_DEBUG7, "Resubmitting %u shares due to stratum disconnect on pool %u", resubmitted, pool->pool_no);
5999 }
6000}
6001
6002static void clear_pool_work(struct pool *pool)
6003{
6004 struct work *work, *tmp;
6005 int cleared = 0;
6006
6007 mutex_lock(stgd_lock);
6008 HASH_ITER(hh, staged_work, work, tmp)for((work)=(staged_work),(tmp)=(__typeof(work))((staged_work)
?(staged_work)->hh.next:((void*)0)); work; (work)=(tmp),(tmp
)=(__typeof(work))((tmp)?(tmp)->hh.next:((void*)0)))
{
6009 if (work->pool == pool) {
6010 HASH_DEL(staged_work, work)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((work)->hh.prev == ((void*)0)) && ((work)->hh
.next == ((void*)0)) ) { free((staged_work)->hh.tbl->buckets
); ; free((staged_work)->hh.tbl); staged_work = ((void*)0)
; } else { _hd_hh_del = &((work)->hh); if ((work) == (
(void*)(((char*)((staged_work)->hh.tbl->tail)) - (((staged_work
)->hh.tbl)->hho)))) { (staged_work)->hh.tbl->tail
= (UT_hash_handle*)((char*)((work)->hh.prev) + (staged_work
)->hh.tbl->hho); } if ((work)->hh.prev) { ((UT_hash_handle
*)((char*)((work)->hh.prev) + (staged_work)->hh.tbl->
hho))->next = (work)->hh.next; } else { do { (staged_work
) = (__typeof(staged_work))((work)->hh.next); } while(0); }
if (_hd_hh_del->next) { ((UT_hash_handle*)((char*)_hd_hh_del
->next + (staged_work)->hh.tbl->hho))->prev = _hd_hh_del
->prev; } do { _hd_bkt = ((_hd_hh_del->hashv) & (((
staged_work)->hh.tbl->num_buckets) - 1)); } while(0); (
(staged_work)->hh.tbl->buckets[_hd_bkt]).count--; if ((
(staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del
) { ((staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head =
_hd_hh_del->hh_next; } if (_hd_hh_del->hh_prev) { _hd_hh_del
->hh_prev->hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del
->hh_next) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del
->hh_prev; }; (staged_work)->hh.tbl->num_items--; } ;
} while (0)
;
6011 free_work(work);
6012 cleared++;
6013 }
6014 }
6015 mutex_unlock(stgd_lock);
6016}
6017
6018/* We only need to maintain a secondary pool connection when we need the
6019 * capacity to get work from the backup pools while still on the primary */
6020static bool_Bool cnx_needed(struct pool *pool)
6021{
6022 struct pool *cp;
6023
6024 /* Balance strategies need all pools online */
6025 if (pool_strategy == POOL_BALANCE)
6026 return true1;
6027 if (pool_strategy == POOL_LOADBALANCE)
6028 return true1;
6029
6030 /* Idle stratum pool needs something to kick it alive again */
6031 if (pool->has_stratum && pool->idle)
6032 return true1;
6033
6034 /* Getwork pools without opt_fail_only need backup pools up to be able
6035 * to leak shares */
6036 cp = current_pool();
6037 if (cp == pool)
6038 return true1;
6039 if (!cp->has_stratum && (!opt_fail_only || !cp->hdr_path))
6040 return true1;
6041
6042 /* Keep stratum pools alive until at least a minute after their last
6043 * generated work, to ensure we have a channel for any submissions */
6044 if (pool->has_stratum && difftime(time(NULL((void*)0)), pool->last_work_time) < 60)
6045 return true1;
6046
6047 return false0;
6048}
6049
6050static void wait_lpcurrent(struct pool *pool);
6051static void pool_resus(struct pool *pool);
6052static void gen_stratum_work(struct pool *pool, struct work *work);
6053
6054static void stratum_resumed(struct pool *pool)
6055{
6056 if (!pool->stratum_notify)
6057 return;
6058 if (pool_tclear(pool, &pool->idle)) {
6059 applog(LOG_INFO6, "Stratum connection to pool %d resumed", pool->pool_no);
6060 pool_resus(pool);
6061 }
6062}
6063
6064static bool_Bool supports_resume(struct pool *pool)
6065{
6066 bool_Bool ret;
6067
6068 mutex_lock(&pool->pool_lock);
6069 ret = (pool->sessionid != NULL((void*)0));
6070 mutex_unlock(&pool->pool_lock);
6071 return ret;
6072}
6073
6074/* One stratum thread per pool that has stratum waits on the socket checking
6075 * for new messages and for the integrity of the socket connection. We reset
6076 * the connection based on the integrity of the receive side only as the send
6077 * side will eventually expire data it fails to send. */
6078static void *stratum_thread(void *userdata)
6079{
6080 struct pool *pool = (struct pool *)userdata;
6081
6082 pthread_detach(pthread_self());
6083
6084 char threadname[20];
6085 snprintf(threadname, 20, "stratum%u", pool->pool_no);
6086 RenameThread(threadname);
6087
6088 srand(time(NULL((void*)0)) + (intptr_t)userdata);
6089
6090 while (42) {
6091 struct timeval timeout;
6092 fd_set rd;
6093 char *s;
6094
6095 if (unlikely(!pool->has_stratum)(!pool->has_stratum))
6096 break;
6097
6098 /* Check to see whether we need to maintain this connection
6099 * indefinitely or just bring it up when we switch to this
6100 * pool */
6101 if (!sock_full(pool) && !cnx_needed(pool)) {
6102 suspend_stratum(pool);
6103 clear_stratum_shares(pool);
6104 clear_pool_work(pool);
6105
6106 wait_lpcurrent(pool);
6107 if (!restart_stratum(pool)) {
6108 pool_died(pool);
6109 while (!restart_stratum(pool)) {
6110 if (pool->removed)
6111 goto out;
6112 sleep(30);
6113 }
6114 }
6115 }
6116
6117 FD_ZERO(&rd)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; stosl" :
"=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof
(__fd_mask)), "1" (&((&rd)->fds_bits)[0]) : "memory"
); } while (0)
;
6118 FD_SET(pool->sock, &rd)((void) (((&rd)->fds_bits)[((pool->sock) / (8 * (int
) sizeof (__fd_mask)))] |= ((__fd_mask) 1 << ((pool->
sock) % (8 * (int) sizeof (__fd_mask))))))
;
6119 timeout.tv_sec = 120;
6120 timeout.tv_usec = 0;
6121
6122 /* If we fail to receive any notify messages for 2 minutes we
6123 * assume the connection has been dropped and treat this pool
6124 * as dead */
6125 if (!sock_full(pool) && select(pool->sock + 1, &rd, NULL((void*)0), NULL((void*)0), &timeout) < 1) {
6126 applog(LOG_DEBUG7, "Stratum select timeout on pool %d", pool->pool_no);
6127 s = NULL((void*)0);
6128 } else
6129 s = recv_line(pool);
6130 if (!s) {
6131 if (!pool->has_stratum)
6132 break;
6133
6134 applog(LOG_NOTICE5, "Stratum connection to pool %d interrupted", pool->pool_no);
6135 pool->getfail_occasions++;
6136 total_go++;
6137
6138 pool->sock = INVSOCK-1;
6139
6140 /* If the socket to our stratum pool disconnects, all
6141 * submissions need to be discarded or resent. */
6142 if (!supports_resume(pool))
6143 clear_stratum_shares(pool);
6144 else
6145 resubmit_stratum_shares(pool);
6146 clear_pool_work(pool);
6147 if (pool == current_pool())
6148 restart_threads();
6149
6150 if (restart_stratum(pool))
6151 continue;
6152
6153 shutdown_stratum(pool);
6154 pool_died(pool);
6155 break;
6156 }
6157
6158 /* Check this pool hasn't died while being a backup pool and
6159 * has not had its idle flag cleared */
6160 stratum_resumed(pool);
6161
6162 if (!parse_method(pool, s) && !parse_stratum_response(pool, s))
6163 applog(LOG_INFO6, "Unknown stratum msg: %s", s);
6164 free(s);
6165 if (pool->swork.clean) {
6166 struct work *work = make_work();
6167
6168 /* Generate a single work item to update the current
6169 * block database */
6170 pool->swork.clean = false0;
6171 gen_stratum_work(pool, work);
6172
6173 /* Try to extract block height from coinbase scriptSig */
6174 char *hex_height = &pool->swork.coinbase1[8 /*version*/ + 2 /*txin count*/ + 72 /*prevout*/ + 2 /*scriptSig len*/ + 2 /*push opcode*/];
6175 unsigned char cb_height_sz;
6176 hex2bin(&cb_height_sz, &hex_height[-2], 1);
6177 if (cb_height_sz == 3) {
6178 // FIXME: The block number will overflow this by AD 2173
6179 uint32_t block_id = ((uint32_t*)work->data)[1];
6180 uint32_t height = 0;
6181 hex2bin((unsigned char*)&height, hex_height, 3);
6182 height = le32toh(height)(height);
6183 have_block_height(block_id, height);
6184 }
6185
6186 ++pool->work_restart_id;
6187 if (test_work_current(work)) {
6188 /* Only accept a work update if this stratum
6189 * connection is from the current pool */
6190 if (pool == current_pool()) {
6191 restart_threads();
6192 applog(
6193 (opt_quiet_work_updates ? LOG_DEBUG7 : LOG_NOTICE5),
6194 "Stratum from pool %d requested work update", pool->pool_no);
6195 }
6196 } else
6197 applog(LOG_NOTICE5, "Stratum from pool %d detected new block", pool->pool_no);
6198 free_work(work);
6199 }
6200
6201 if (pool->swork.transparency_time != (time_t)-1 && difftime(time(NULL((void*)0)), pool->swork.transparency_time) > 21.09375) {
6202 // More than 4 timmills past since requested transactions
6203 pool->swork.transparency_time = (time_t)-1;
6204 pool->swork.opaque = true1;
6205 applog(LOG_WARNING4, "Pool %u is hiding block contents from us",
6206 pool->pool_no);
6207 }
6208 }
6209
6210out:
6211 return NULL((void*)0);
6212}
6213
6214static void init_stratum_thread(struct pool *pool)
6215{
6216 if (unlikely(pthread_create(&pool->stratum_thread, NULL, stratum_thread, (void *)pool))(pthread_create(&pool->stratum_thread, ((void*)0), stratum_thread
, (void *)pool))
)
6217 quit(1, "Failed to create stratum thread");
6218}
6219
6220static void *longpoll_thread(void *userdata);
6221
6222static bool_Bool stratum_works(struct pool *pool)
6223{
6224 applog(LOG_INFO6, "Testing pool %d stratum %s", pool->pool_no, pool->stratum_url);
6225 if (!extract_sockaddr(pool, pool->stratum_url))
6226 return false0;
6227
6228 if (!initiate_stratum(pool))
6229 return false0;
6230
6231 return true1;
6232}
6233
6234static bool_Bool pool_active(struct pool *pool, bool_Bool pinging)
6235{
6236 struct timeval tv_getwork, tv_getwork_reply;
6237 bool_Bool ret = false0;
6238 json_t *val;
6239 CURL *curl;
6240 int rolltime;
6241 char *rpc_req;
6242 struct work *work;
6243 enum pool_protocol proto;
6244
6245 applog(LOG_INFO6, "Testing pool %s", pool->rpc_url);
6246
6247 /* This is the central point we activate stratum when we can */
6248 curl = curl_easy_init();
6249 if (unlikely(!curl)(!curl)) {
6250 applog(LOG_ERR3, "CURL initialisation failed");
6251 return false0;
6252 }
6253
6254 if (!(want_gbt || want_getwork))
6255 goto nohttp;
6256
6257 work = make_work();
6258
6259 /* Probe for GBT support on first pass */
6260 proto = want_gbt ? PLP_GETBLOCKTEMPLATE : PLP_GETWORK;
6261
6262tryagain:
6263 rpc_req = prepare_rpc_req_probe(work, proto, NULL)prepare_rpc_req2(work, proto, ((void*)0), 1);
6264 work->pool = pool;
6265 if (!rpc_req)
6266 goto out;
6267
6268 pool->probed = false0;
6269 gettimeofday(&tv_getwork, NULL((void*)0));
6270 val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req,
6271 true1, false0, &rolltime, pool, false0);
6272 gettimeofday(&tv_getwork_reply, NULL((void*)0));
6273
6274 free(rpc_req);
6275
6276 /* Detect if a http getwork pool has an X-Stratum header at startup,
6277 * and if so, switch to that in preference to getwork if it works */
6278 if (pool->stratum_url && want_stratum && (pool->has_stratum || stratum_works(pool))) {
6279 if (!pool->has_stratum) {
6280
6281 applog(LOG_NOTICE5, "Switching pool %d %s to %s", pool->pool_no, pool->rpc_url, pool->stratum_url);
6282 if (!pool->rpc_url)
6283 pool->rpc_url = strdup(pool->stratum_url);
6284 pool->has_stratum = true1;
6285
6286 }
6287
6288 free_work(work);
6289 if (val)
6290 json_decref(val);
6291
6292retry_stratum:
6293 curl_easy_cleanup(curl);
6294
6295 /* We create the stratum thread for each pool just after
6296 * successful authorisation. Once the auth flag has been set
6297 * we never unset it and the stratum thread is responsible for
6298 * setting/unsetting the active flag */
6299 if (pool->stratum_auth)
6300 return pool->stratum_active;
6301 if (!(pool->stratum_active ? auth_stratum(pool) : restart_stratum(pool)))
6302 return false0;
6303 init_stratum_thread(pool);
6304 detect_algo = 2;
6305 return true1;
6306 }
6307 else if (pool->has_stratum)
6308 shutdown_stratum(pool);
6309
6310 if (val) {
6311 bool_Bool rc;
6312 json_t *res;
6313
6314 res = json_object_get(val, "result");
6315 if ((!json_is_object(res)(res && ((res)->type) == JSON_OBJECT)) || (proto == PLP_GETBLOCKTEMPLATE && !json_object_get(res, "bits")))
6316 goto badwork;
6317
6318 work->rolltime = rolltime;
6319 rc = work_decode(pool, work, val);
6320 if (rc) {
6321 applog(LOG_DEBUG7, "Successfully retrieved and deciphered work from pool %u %s",
6322 pool->pool_no, pool->rpc_url);
6323 work->pool = pool;
6324 memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval));
6325 memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval));
6326 work->getwork_mode = GETWORK_MODE_TESTPOOL'T';
6327 calc_diff(work, 0);
6328
6329 update_last_work(work);
6330
6331 applog(LOG_DEBUG7, "Pushing pooltest work to base pool");
6332
6333 tq_push(thr_info[stage_thr_id].q, work);
6334 total_getworks++;
6335 pool->getwork_requested++;
6336 ret = true1;
6337 gettimeofday(&pool->tv_idle, NULL((void*)0));
6338 } else {
6339badwork:
6340 json_decref(val);
6341 applog(LOG_DEBUG7, "Successfully retrieved but FAILED to decipher work from pool %u %s",
6342 pool->pool_no, pool->rpc_url);
6343 pool->proto = proto = pool_protocol_fallback(proto);
6344 if (PLP_NONE != proto)
6345 goto tryagain;
6346 free_work(work);
6347 goto out;
6348 }
6349 json_decref(val);
6350
6351 if (proto != pool->proto) {
6352 pool->proto = proto;
6353 applog(LOG_INFO6, "Selected %s protocol for pool %u", pool_protocol_name(proto), pool->pool_no);
6354 }
6355
6356 if (pool->lp_url)
6357 goto out;
6358
6359 /* Decipher the longpoll URL, if any, and store it in ->lp_url */
6360
6361 const struct blktmpl_longpoll_req *lp;
6362 if (work->tmpl && (lp = blktmpl_get_longpoll(work->tmpl))) {
6363 // NOTE: work_decode takes care of lp id
6364 pool->lp_url = lp->uri ? absolute_uri(lp->uri, pool->rpc_url) : pool->rpc_url;
6365 if (!pool->lp_url)
6366 {
6367 ret = false0;
6368 goto out;
6369 }
6370 pool->lp_proto = PLP_GETBLOCKTEMPLATE;
6371 }
6372 else
6373 if (pool->hdr_path && want_getwork) {
6374 pool->lp_url = absolute_uri(pool->hdr_path, pool->rpc_url);
6375 if (!pool->lp_url)
6376 {
6377 ret = false0;
6378 goto out;
6379 }
6380 pool->lp_proto = PLP_GETWORK;
6381 } else
6382 pool->lp_url = NULL((void*)0);
6383
6384 if (want_longpoll && !pool->lp_started) {
6385 pool->lp_started = true1;
6386 if (unlikely(pthread_create(&pool->longpoll_thread, NULL, longpoll_thread, (void *)pool))(pthread_create(&pool->longpoll_thread, ((void*)0), longpoll_thread
, (void *)pool))
)
6387 quit(1, "Failed to create pool longpoll thread");
6388 }
6389 } else if (PLP_NONE != (proto = pool_protocol_fallback(proto))) {
6390 pool->proto = proto;
6391 goto tryagain;
6392 } else {
6393 free_work(work);
6394nohttp:
6395 /* If we failed to parse a getwork, this could be a stratum
6396 * url without the prefix stratum+tcp:// so let's check it */
6397 if (extract_sockaddr(pool, pool->rpc_url) && initiate_stratum(pool)) {
6398 pool->has_stratum = true1;
6399 goto retry_stratum;
6400 }
6401 applog(LOG_DEBUG7, "FAILED to retrieve work from pool %u %s",
6402 pool->pool_no, pool->rpc_url);
6403 if (!pinging)
6404 applog(LOG_WARNING4, "Pool %u slow/down or URL or credentials invalid", pool->pool_no);
6405 }
6406out:
6407 curl_easy_cleanup(curl);
6408 return ret;
6409}
6410
6411static inline int cp_prio(void)
6412{
6413 int prio;
6414
6415 mutex_lock(&control_lock);
6416 prio = currentpool->prio;
6417 mutex_unlock(&control_lock);
6418 return prio;
6419}
6420
6421static void pool_resus(struct pool *pool)
6422{
6423 if (pool->prio < cp_prio() && pool_strategy == POOL_FAILOVER) {
6424 applog(LOG_WARNING4, "Pool %d %s alive", pool->pool_no, pool->rpc_url);
6425 switch_pools(NULL((void*)0));
6426 } else
6427 applog(LOG_INFO6, "Pool %d %s resumed returning work", pool->pool_no, pool->rpc_url);
6428}
6429
6430static struct work *hash_pop(void)
6431{
6432 struct work *work = NULL((void*)0), *tmp;
6433 int hc;
6434
6435retry:
6436 mutex_lock(stgd_lock);
6437 while (!getq->frozen && !HASH_COUNT(staged_work)((staged_work)?((staged_work)->hh.tbl->num_items):0))
6438 pthread_cond_wait(&getq->cond, stgd_lock);
6439
6440 hc = HASH_COUNT(staged_work)((staged_work)?((staged_work)->hh.tbl->num_items):0);
6441 /* Find clone work if possible, to allow masters to be reused */
6442 if (hc > staged_rollable) {
6443 HASH_ITER(hh, staged_work, work, tmp)for((work)=(staged_work),(tmp)=(__typeof(work))((staged_work)
?(staged_work)->hh.next:((void*)0)); work; (work)=(tmp),(tmp
)=(__typeof(work))((tmp)?(tmp)->hh.next:((void*)0)))
{
6444 if (!work_rollable(work))
6445 break;
6446 }
6447 } else
6448 work = staged_work;
6449
6450 if (can_roll(work) && should_roll(work))
6451 {
6452 // Instead of consuming it, force it to be cloned and grab the clone
6453 mutex_unlock(stgd_lock);
6454 clone_available();
6455 goto retry;
6456 }
6457
6458 HASH_DEL(staged_work, work)do { unsigned _hd_bkt; struct UT_hash_handle *_hd_hh_del; if (
((work)->hh.prev == ((void*)0)) && ((work)->hh
.next == ((void*)0)) ) { free((staged_work)->hh.tbl->buckets
); ; free((staged_work)->hh.tbl); staged_work = ((void*)0)
; } else { _hd_hh_del = &((work)->hh); if ((work) == (
(void*)(((char*)((staged_work)->hh.tbl->tail)) - (((staged_work
)->hh.tbl)->hho)))) { (staged_work)->hh.tbl->tail
= (UT_hash_handle*)((char*)((work)->hh.prev) + (staged_work
)->hh.tbl->hho); } if ((work)->hh.prev) { ((UT_hash_handle
*)((char*)((work)->hh.prev) + (staged_work)->hh.tbl->
hho))->next = (work)->hh.next; } else { do { (staged_work
) = (__typeof(staged_work))((work)->hh.next); } while(0); }
if (_hd_hh_del->next) { ((UT_hash_handle*)((char*)_hd_hh_del
->next + (staged_work)->hh.tbl->hho))->prev = _hd_hh_del
->prev; } do { _hd_bkt = ((_hd_hh_del->hashv) & (((
staged_work)->hh.tbl->num_buckets) - 1)); } while(0); (
(staged_work)->hh.tbl->buckets[_hd_bkt]).count--; if ((
(staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head == _hd_hh_del
) { ((staged_work)->hh.tbl->buckets[_hd_bkt]).hh_head =
_hd_hh_del->hh_next; } if (_hd_hh_del->hh_prev) { _hd_hh_del
->hh_prev->hh_next = _hd_hh_del->hh_next; } if (_hd_hh_del
->hh_next) { _hd_hh_del->hh_next->hh_prev = _hd_hh_del
->hh_prev; }; (staged_work)->hh.tbl->num_items--; } ;
} while (0)
;
6459 if (work_rollable(work))
6460 staged_rollable--;
6461
6462 /* Signal the getwork scheduler to look for more work */
6463 pthread_cond_signal(&gws_cond);
6464
6465 /* Signal hash_pop again in case there are mutliple hash_pop waiters */
6466 pthread_cond_signal(&getq->cond);
6467 mutex_unlock(stgd_lock);
6468
6469 return work;
6470}
6471
6472/* Clones work by rolling it if possible, and returning a clone instead of the
6473 * original work item which gets staged again to possibly be rolled again in
6474 * the future */
6475static struct work *clone_work(struct work *work)
6476{
6477 int mrs = mining_threads + opt_queue - total_staged();
6478 struct work *work_clone;
6479 bool_Bool cloned;
6480
6481 if (mrs < 1)
6482 return work;
6483
6484 cloned = false0;
6485 work_clone = make_clone(work);
6486 while (mrs-- > 0 && can_roll(work) && should_roll(work)) {
6487 applog(LOG_DEBUG7, "Pushing rolled converted work to stage thread");
6488 stage_work(work_clone);
6489 roll_work(work);
6490 work_clone = make_clone(work);
6491 /* Roll it again to prevent duplicates should this be used
6492 * directly later on */
6493 roll_work(work);
6494 cloned = true1;
6495 }
6496
6497 if (cloned) {
6498 stage_work(work);
6499 return work_clone;
6500 }
6501
6502 free_work(work_clone);
6503
6504 return work;
6505}
6506
6507void gen_hash(unsigned char *data, unsigned char *hash, int len)
6508{
6509 unsigned char hash1[32];
6510
6511 sha2(data, len, hash1);
6512 sha2(hash1, 32, hash);
6513}
6514
6515/* Diff 1 is a 256 bit unsigned integer of
6516 * 0x00000000ffff0000000000000000000000000000000000000000000000000000
6517 * so we use a big endian 64 bit unsigned integer centred on the 5th byte to
6518 * cover a huge range of difficulty targets, though not all 256 bits' worth */
6519static void bdiff_target_leadzero(unsigned char *target, double diff)
6520{
6521 uint64_t *data64, h64;
6522 double d64;
6523
6524 d64 = diffone;
6525 d64 /= diff;
6526 d64 = ceil(d64);
6527 h64 = d64;
6528
6529 memset(target, 0, 32);
6530 if (d64 < 18446744073709551616.0) {
6531 unsigned char *rtarget = target;
6532 memset(rtarget, 0, 32);
6533 if (opt_scrypt)
6534 data64 = (uint64_t *)(rtarget + 2);
6535 else
6536 data64 = (uint64_t *)(rtarget + 4);
6537 *data64 = htobe64(h64)(__extension__ ({ union { __extension__ unsigned long long int
__ll; unsigned long int __l[2]; } __w, __r; if (__builtin_constant_p
(h64)) __r.__ll = (__extension__ ((((h64) & 0xff00000000000000ull
) >> 56) | (((h64) & 0x00ff000000000000ull) >>
40) | (((h64) & 0x0000ff0000000000ull) >> 24) | ((
(h64) & 0x000000ff00000000ull) >> 8) | (((h64) &
0x00000000ff000000ull) << 8) | (((h64) & 0x0000000000ff0000ull
) << 24) | (((h64) & 0x000000000000ff00ull) <<
40) | (((h64) & 0x00000000000000ffull) << 56))); else
{ __w.__ll = (h64); __r.__l[0] = (__extension__ ({ register unsigned
int __v, __x = (__w.__l[1]); if (__builtin_constant_p (__x))
__v = ((((__x) & 0xff000000) >> 24) | (((__x) &
0x00ff0000) >> 8) | (((__x) & 0x0000ff00) <<
8) | (((__x) & 0x000000ff) << 24)); else __asm__ (
"bswap %0" : "=r" (__v) : "0" (__x)); __v; })); __r.__l[1] = (
__extension__ ({ register unsigned int __v, __x = (__w.__l[0]
); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000
) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x
) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) <<
24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v
; })); } __r.__ll; }))
;
6538 } else {
6539 /* Support for the classic all FFs just-below-1 diff */
6540 if (opt_scrypt)
6541 memset(&target[2], 0xff, 30);
6542 else
6543 memset(&target[4], 0xff, 28);
6544 }
6545}
6546
6547static inline
6548void set_work_target(struct work *work, double diff)
6549{
6550 unsigned char rtarget[32];
6551 bdiff_target_leadzero(rtarget, diff);
6552 swab256(work->target, rtarget);
6553
6554 if (opt_debug) {
6555 char *htarget = bin2hex(rtarget, 32);
6556
6557 applog(LOG_DEBUG7, "Generated target %s", htarget);
6558 free(htarget);
6559 }
6560}
6561
6562/* Generates stratum based work based on the most recent notify information
6563 * from the pool. This will keep generating work while a pool is down so we use
6564 * other means to detect when the pool has died in stratum_thread */
6565static void gen_stratum_work(struct pool *pool, struct work *work)
6566{
6567 unsigned char *coinbase, merkle_root[32], merkle_sha[64];
6568 char *header, *merkle_hash;
6569 uint32_t *data32, *swap32;
6570 size_t alloc_len;
6571 int i;
6572
6573 clean_work(work);
6574
6575 mutex_lock(&pool->pool_lock);
6576
6577 /* Generate coinbase */
6578 work->nonce2 = bin2hex((const unsigned char *)&pool->nonce2, pool->n2size);
6579 pool->nonce2++;
6580 alloc_len = pool->swork.cb_len;
6581 align_len(&alloc_len);
6582 coinbase = calloc(alloc_len, 1);
6583 if (unlikely(!coinbase)(!coinbase))
6584 quit(1, "Failed to calloc coinbase in gen_stratum_work");
6585 hex2bin(coinbase, pool->swork.coinbase1, pool->swork.cb1_len);
6586 hex2bin(coinbase + pool->swork.cb1_len, pool->nonce1, pool->n1_len);
6587 hex2bin(coinbase + pool->swork.cb1_len + pool->n1_len, work->nonce2, pool->n2size);
6588 hex2bin(coinbase + pool->swork.cb1_len + pool->n1_len + pool->n2size, pool->swork.coinbase2, pool->swork.cb2_len);
6589
6590 /* Generate merkle root */
6591 gen_hash(coinbase, merkle_root, pool->swork.cb_len);
6592 free(coinbase);
6593 memcpy(merkle_sha, merkle_root, 32);
6594 for (i = 0; i < pool->swork.merkles; i++) {
6595 unsigned char merkle_bin[32];
6596
6597 hex2bin(merkle_bin, pool->swork.merkle[i], 32);
6598 memcpy(merkle_sha + 32, merkle_bin, 32);
6599 gen_hash(merkle_sha, merkle_root, 64);
6600 memcpy(merkle_sha, merkle_root, 32);
6601 }
6602 data32 = (uint32_t *)merkle_sha;
6603 swap32 = (uint32_t *)merkle_root;
6604 for (i = 0; i < 32 / 4; i++)
6605 swap32[i] = swab32(data32[i]);
6606 merkle_hash = bin2hex((const unsigned char *)merkle_root, 32);
6607
6608 header = calloc(pool->swork.header_len, 1);
6609 if (unlikely(!header)(!header))
6610 quit(1, "Failed to calloc header in gen_stratum_work");
6611 sprintf(header, "%s%s%s%s%s%s%s",
6612 pool->swork.bbversion,
6613 pool->swork.prev_hash,
6614 merkle_hash,
6615 pool->swork.ntime,
6616