cpu-miner.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. /*
  2. * Copyright 2010 Jeff Garzik
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU General Public License as published by the Free
  6. * Software Foundation; either version 2 of the License, or (at your option)
  7. * any later version. See COPYING for more details.
  8. */
  9. #include "cpuminer-config.h"
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdbool.h>
  14. #include <stdint.h>
  15. #include <unistd.h>
  16. #include <sys/time.h>
  17. #include <time.h>
  18. #ifndef WIN32
  19. #include <sys/resource.h>
  20. #endif
  21. #include <getopt.h>
  22. #include <jansson.h>
  23. #include <curl/curl.h>
  24. #include "compat.h"
  25. #include "miner.h"
  26. #define PROGRAM_NAME "minerd"
  27. #define DEF_RPC_URL "http://127.0.0.1:8332/"
  28. #define DEF_RPC_USERPASS "rpcuser:rpcpass"
  29. enum workio_commands {
  30. WC_GET_WORK,
  31. WC_SUBMIT_WORK,
  32. };
  33. struct workio_cmd {
  34. enum workio_commands cmd;
  35. struct thr_info *thr;
  36. union {
  37. struct work *work;
  38. } u;
  39. };
  40. enum sha256_algos {
  41. ALGO_C, /* plain C */
  42. ALGO_4WAY, /* parallel SSE2 */
  43. ALGO_VIA, /* VIA padlock */
  44. ALGO_CRYPTOPP, /* Crypto++ (C) */
  45. ALGO_CRYPTOPP_ASM32, /* Crypto++ 32-bit assembly */
  46. ALGO_SSE2_64, /* SSE2 for x86_64 */
  47. };
  48. static const char *algo_names[] = {
  49. [ALGO_C] = "c",
  50. #ifdef WANT_SSE2_4WAY
  51. [ALGO_4WAY] = "4way",
  52. #endif
  53. #ifdef WANT_VIA_PADLOCK
  54. [ALGO_VIA] = "via",
  55. #endif
  56. [ALGO_CRYPTOPP] = "cryptopp",
  57. #ifdef WANT_CRYPTOPP_ASM32
  58. [ALGO_CRYPTOPP_ASM32] = "cryptopp_asm32",
  59. #endif
  60. #ifdef WANT_X8664_SSE2
  61. [ALGO_SSE2_64] = "sse2_64",
  62. #endif
  63. };
  64. bool opt_debug = false;
  65. bool opt_protocol = false;
  66. bool want_longpoll = true;
  67. bool have_longpoll = false;
  68. bool use_syslog = false;
  69. static bool opt_quiet = false;
  70. static int opt_retries = 10;
  71. static int opt_fail_pause = 30;
  72. int opt_scantime = 5;
  73. static json_t *opt_config;
  74. static const bool opt_time = true;
  75. static enum sha256_algos opt_algo = ALGO_C;
  76. static int opt_n_threads = 1;
  77. static char *rpc_url;
  78. static char *userpass;
  79. struct thr_info *thr_info;
  80. static int work_thr_id;
  81. int longpoll_thr_id;
  82. struct work_restart *work_restart = NULL;
  83. pthread_mutex_t time_lock;
  84. struct option_help {
  85. const char *name;
  86. const char *helptext;
  87. };
  88. static struct option_help options_help[] = {
  89. { "help",
  90. "(-h) Display this help text" },
  91. { "config FILE",
  92. "(-c FILE) JSON-format configuration file (default: none)\n"
  93. "See example-cfg.json for an example configuration." },
  94. { "algo XXX",
  95. "(-a XXX) Specify sha256 implementation:\n"
  96. "\tc\t\tLinux kernel sha256, implemented in C (default)"
  97. #ifdef WANT_SSE2_4WAY
  98. "\n\t4way\t\ttcatm's 4-way SSE2 implementation"
  99. #endif
  100. #ifdef WANT_VIA_PADLOCK
  101. "\n\tvia\t\tVIA padlock implementation"
  102. #endif
  103. "\n\tcryptopp\tCrypto++ C/C++ implementation"
  104. #ifdef WANT_CRYPTOPP_ASM32
  105. "\n\tcryptopp_asm32\tCrypto++ 32-bit assembler implementation"
  106. #endif
  107. #ifdef WANT_X8664_SSE2
  108. "\n\tsse2_64\t\tSSE2 implementation for x86_64 machines"
  109. #endif
  110. },
  111. { "quiet",
  112. "(-q) Disable per-thread hashmeter output (default: off)" },
  113. { "debug",
  114. "(-D) Enable debug output (default: off)" },
  115. { "no-longpoll",
  116. "Disable X-Long-Polling support (default: enabled)" },
  117. { "protocol-dump",
  118. "(-P) Verbose dump of protocol-level activities (default: off)" },
  119. { "retries N",
  120. "(-r N) Number of times to retry, if JSON-RPC call fails\n"
  121. "\t(default: 10; use -1 for \"never\")" },
  122. { "retry-pause N",
  123. "(-R N) Number of seconds to pause, between retries\n"
  124. "\t(default: 30)" },
  125. { "scantime N",
  126. "(-s N) Upper bound on time spent scanning current work,\n"
  127. "\tin seconds. (default: 5)" },
  128. #ifdef HAVE_SYSLOG_H
  129. { "syslog",
  130. "Use system log for output messages (default: standard error)" },
  131. #endif
  132. { "threads N",
  133. "(-t N) Number of miner threads (default: 1)" },
  134. { "url URL",
  135. "URL for bitcoin JSON-RPC server "
  136. "(default: " DEF_RPC_URL ")" },
  137. { "userpass USERNAME:PASSWORD",
  138. "Username:Password pair for bitcoin JSON-RPC server "
  139. "(default: " DEF_RPC_USERPASS ")" },
  140. };
  141. static struct option options[] = {
  142. { "help", 0, NULL, 'h' },
  143. { "algo", 1, NULL, 'a' },
  144. { "config", 1, NULL, 'c' },
  145. { "quiet", 0, NULL, 'q' },
  146. { "debug", 0, NULL, 'D' },
  147. { "protocol-dump", 0, NULL, 'P' },
  148. { "threads", 1, NULL, 't' },
  149. { "retries", 1, NULL, 'r' },
  150. { "retry-pause", 1, NULL, 'R' },
  151. { "scantime", 1, NULL, 's' },
  152. { "url", 1, NULL, 1001 },
  153. { "userpass", 1, NULL, 1002 },
  154. { "no-longpoll", 0, NULL, 1003 },
  155. #ifdef HAVE_SYSLOG_H
  156. { "syslog", 0, NULL, 1004 },
  157. #endif
  158. { }
  159. };
  160. struct work {
  161. unsigned char data[128];
  162. unsigned char hash1[64];
  163. unsigned char midstate[32];
  164. unsigned char target[32];
  165. unsigned char hash[32];
  166. };
  167. static bool jobj_binary(const json_t *obj, const char *key,
  168. void *buf, size_t buflen)
  169. {
  170. const char *hexstr;
  171. json_t *tmp;
  172. tmp = json_object_get(obj, key);
  173. if (!tmp) {
  174. applog(LOG_ERR, "JSON key '%s' not found", key);
  175. return false;
  176. }
  177. hexstr = json_string_value(tmp);
  178. if (!hexstr) {
  179. applog(LOG_ERR, "JSON key '%s' is not a string", key);
  180. return false;
  181. }
  182. if (!hex2bin(buf, hexstr, buflen))
  183. return false;
  184. return true;
  185. }
  186. static bool work_decode(const json_t *val, struct work *work)
  187. {
  188. if (!jobj_binary(val, "midstate",
  189. work->midstate, sizeof(work->midstate))) {
  190. applog(LOG_ERR, "JSON inval midstate");
  191. goto err_out;
  192. }
  193. if (!jobj_binary(val, "data", work->data, sizeof(work->data))) {
  194. applog(LOG_ERR, "JSON inval data");
  195. goto err_out;
  196. }
  197. if (!jobj_binary(val, "hash1", work->hash1, sizeof(work->hash1))) {
  198. applog(LOG_ERR, "JSON inval hash1");
  199. goto err_out;
  200. }
  201. if (!jobj_binary(val, "target", work->target, sizeof(work->target))) {
  202. applog(LOG_ERR, "JSON inval target");
  203. goto err_out;
  204. }
  205. memset(work->hash, 0, sizeof(work->hash));
  206. return true;
  207. err_out:
  208. return false;
  209. }
  210. static bool submit_upstream_work(CURL *curl, const struct work *work)
  211. {
  212. char *hexstr = NULL;
  213. json_t *val, *res;
  214. char s[345];
  215. bool rc = false;
  216. /* build hex string */
  217. hexstr = bin2hex(work->data, sizeof(work->data));
  218. if (!hexstr) {
  219. applog(LOG_ERR, "submit_upstream_work OOM");
  220. goto out;
  221. }
  222. /* build JSON-RPC request */
  223. sprintf(s,
  224. "{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
  225. hexstr);
  226. if (opt_debug)
  227. applog(LOG_DEBUG, "DBG: sending RPC call: %s", s);
  228. /* issue JSON-RPC request */
  229. val = json_rpc_call(curl, rpc_url, userpass, s, false, false);
  230. if (!val) {
  231. applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
  232. goto out;
  233. }
  234. res = json_object_get(val, "result");
  235. applog(LOG_INFO, "PROOF OF WORK RESULT: %s",
  236. json_is_true(res) ? "true (yay!!!)" : "false (booooo)");
  237. json_decref(val);
  238. rc = true;
  239. out:
  240. free(hexstr);
  241. return rc;
  242. }
  243. static const char *rpc_req =
  244. "{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
  245. static bool get_upstream_work(CURL *curl, struct work *work)
  246. {
  247. json_t *val;
  248. bool rc;
  249. val = json_rpc_call(curl, rpc_url, userpass, rpc_req,
  250. want_longpoll, false);
  251. if (!val)
  252. return false;
  253. rc = work_decode(json_object_get(val, "result"), work);
  254. json_decref(val);
  255. return rc;
  256. }
  257. static void workio_cmd_free(struct workio_cmd *wc)
  258. {
  259. if (!wc)
  260. return;
  261. switch (wc->cmd) {
  262. case WC_SUBMIT_WORK:
  263. free(wc->u.work);
  264. break;
  265. default: /* do nothing */
  266. break;
  267. }
  268. memset(wc, 0, sizeof(*wc)); /* poison */
  269. free(wc);
  270. }
  271. static bool workio_get_work(struct workio_cmd *wc, CURL *curl)
  272. {
  273. struct work *ret_work;
  274. int failures = 0;
  275. ret_work = calloc(1, sizeof(*ret_work));
  276. if (!ret_work)
  277. return false;
  278. /* obtain new work from bitcoin via JSON-RPC */
  279. while (!get_upstream_work(curl, ret_work)) {
  280. if ((opt_retries >= 0) && (++failures > opt_retries)) {
  281. applog(LOG_ERR, "json_rpc_call failed, terminating workio thread");
  282. free(ret_work);
  283. return false;
  284. }
  285. /* pause, then restart work-request loop */
  286. applog(LOG_ERR, "json_rpc_call failed, retry after %d seconds",
  287. opt_fail_pause);
  288. sleep(opt_fail_pause);
  289. }
  290. /* send work to requesting thread */
  291. if (!tq_push(wc->thr->q, ret_work))
  292. free(ret_work);
  293. return true;
  294. }
  295. static bool workio_submit_work(struct workio_cmd *wc, CURL *curl)
  296. {
  297. int failures = 0;
  298. /* submit solution to bitcoin via JSON-RPC */
  299. while (!submit_upstream_work(curl, wc->u.work)) {
  300. if ((opt_retries >= 0) && (++failures > opt_retries)) {
  301. applog(LOG_ERR, "...terminating workio thread");
  302. return false;
  303. }
  304. /* pause, then restart work-request loop */
  305. applog(LOG_ERR, "...retry after %d seconds",
  306. opt_fail_pause);
  307. sleep(opt_fail_pause);
  308. }
  309. return true;
  310. }
  311. static void *workio_thread(void *userdata)
  312. {
  313. struct thr_info *mythr = userdata;
  314. CURL *curl;
  315. bool ok = true;
  316. curl = curl_easy_init();
  317. if (!curl) {
  318. applog(LOG_ERR, "CURL initialization failed");
  319. return NULL;
  320. }
  321. while (ok) {
  322. struct workio_cmd *wc;
  323. /* wait for workio_cmd sent to us, on our queue */
  324. wc = tq_pop(mythr->q, NULL);
  325. if (!wc) {
  326. ok = false;
  327. break;
  328. }
  329. /* process workio_cmd */
  330. switch (wc->cmd) {
  331. case WC_GET_WORK:
  332. ok = workio_get_work(wc, curl);
  333. break;
  334. case WC_SUBMIT_WORK:
  335. ok = workio_submit_work(wc, curl);
  336. break;
  337. default: /* should never happen */
  338. ok = false;
  339. break;
  340. }
  341. workio_cmd_free(wc);
  342. }
  343. tq_freeze(mythr->q);
  344. curl_easy_cleanup(curl);
  345. return NULL;
  346. }
  347. static void hashmeter(int thr_id, const struct timeval *diff,
  348. unsigned long hashes_done)
  349. {
  350. double khashes, secs;
  351. khashes = hashes_done / 1000.0;
  352. secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
  353. if (!opt_quiet)
  354. applog(LOG_INFO, "thread %d: %lu hashes, %.2f khash/sec",
  355. thr_id, hashes_done,
  356. khashes / secs);
  357. }
  358. static bool get_work(struct thr_info *thr, struct work *work)
  359. {
  360. struct workio_cmd *wc;
  361. struct work *work_heap;
  362. /* fill out work request message */
  363. wc = calloc(1, sizeof(*wc));
  364. if (!wc)
  365. return false;
  366. wc->cmd = WC_GET_WORK;
  367. wc->thr = thr;
  368. /* send work request to workio thread */
  369. if (!tq_push(thr_info[work_thr_id].q, wc)) {
  370. workio_cmd_free(wc);
  371. return false;
  372. }
  373. /* wait for response, a unit of work */
  374. work_heap = tq_pop(thr->q, NULL);
  375. if (!work_heap)
  376. return false;
  377. /* copy returned work into storage provided by caller */
  378. memcpy(work, work_heap, sizeof(*work));
  379. free(work_heap);
  380. return true;
  381. }
  382. static bool submit_work(struct thr_info *thr, const struct work *work_in)
  383. {
  384. struct workio_cmd *wc;
  385. /* fill out work request message */
  386. wc = calloc(1, sizeof(*wc));
  387. if (!wc)
  388. return false;
  389. wc->u.work = malloc(sizeof(*work_in));
  390. if (!wc->u.work)
  391. goto err_out;
  392. wc->cmd = WC_SUBMIT_WORK;
  393. wc->thr = thr;
  394. memcpy(wc->u.work, work_in, sizeof(*work_in));
  395. /* send solution to workio thread */
  396. if (!tq_push(thr_info[work_thr_id].q, wc))
  397. goto err_out;
  398. return true;
  399. err_out:
  400. workio_cmd_free(wc);
  401. return false;
  402. }
  403. static void *miner_thread(void *userdata)
  404. {
  405. struct thr_info *mythr = userdata;
  406. int thr_id = mythr->id;
  407. uint32_t max_nonce = 0xffffff;
  408. while (1) {
  409. struct work work __attribute__((aligned(128)));
  410. unsigned long hashes_done;
  411. struct timeval tv_start, tv_end, diff;
  412. uint64_t max64;
  413. bool rc;
  414. /* obtain new work from internal workio thread */
  415. if (!get_work(mythr, &work)) {
  416. applog(LOG_ERR, "work retrieval failed, exiting "
  417. "mining thread %d", mythr->id);
  418. goto out;
  419. }
  420. hashes_done = 0;
  421. gettimeofday(&tv_start, NULL);
  422. /* scan nonces for a proof-of-work hash */
  423. switch (opt_algo) {
  424. case ALGO_C:
  425. rc = scanhash_c(thr_id, work.midstate, work.data + 64,
  426. work.hash1, work.hash, work.target,
  427. max_nonce, &hashes_done);
  428. break;
  429. #ifdef WANT_X8664_SSE2
  430. case ALGO_SSE2_64: {
  431. unsigned int rc5 =
  432. scanhash_sse2_64(thr_id, work.midstate, work.data + 64,
  433. work.hash1, work.hash,
  434. work.target,
  435. max_nonce, &hashes_done);
  436. rc = (rc5 == -1) ? false : true;
  437. }
  438. break;
  439. #endif
  440. #ifdef WANT_SSE2_4WAY
  441. case ALGO_4WAY: {
  442. unsigned int rc4 =
  443. ScanHash_4WaySSE2(thr_id, work.midstate, work.data + 64,
  444. work.hash1, work.hash,
  445. work.target,
  446. max_nonce, &hashes_done);
  447. rc = (rc4 == -1) ? false : true;
  448. }
  449. break;
  450. #endif
  451. #ifdef WANT_VIA_PADLOCK
  452. case ALGO_VIA:
  453. rc = scanhash_via(thr_id, work.data, work.target,
  454. max_nonce, &hashes_done);
  455. break;
  456. #endif
  457. case ALGO_CRYPTOPP:
  458. rc = scanhash_cryptopp(thr_id, work.midstate, work.data + 64,
  459. work.hash1, work.hash, work.target,
  460. max_nonce, &hashes_done);
  461. break;
  462. #ifdef WANT_CRYPTOPP_ASM32
  463. case ALGO_CRYPTOPP_ASM32:
  464. rc = scanhash_asm32(thr_id, work.midstate, work.data + 64,
  465. work.hash1, work.hash, work.target,
  466. max_nonce, &hashes_done);
  467. break;
  468. #endif
  469. default:
  470. /* should never happen */
  471. goto out;
  472. }
  473. /* record scanhash elapsed time */
  474. gettimeofday(&tv_end, NULL);
  475. timeval_subtract(&diff, &tv_end, &tv_start);
  476. hashmeter(thr_id, &diff, hashes_done);
  477. /* adjust max_nonce to meet target scan time */
  478. if (diff.tv_usec > 500000)
  479. diff.tv_sec++;
  480. if (diff.tv_sec > 0) {
  481. max64 =
  482. ((uint64_t)hashes_done * opt_scantime) / diff.tv_sec;
  483. if (max64 > 0xfffffffaULL)
  484. max64 = 0xfffffffaULL;
  485. max_nonce = max64;
  486. }
  487. /* if nonce found, submit work */
  488. if (rc && !submit_work(mythr, &work))
  489. break;
  490. }
  491. out:
  492. tq_freeze(mythr->q);
  493. return NULL;
  494. }
  495. static void restart_threads(void)
  496. {
  497. int i;
  498. for (i = 0; i < opt_n_threads; i++)
  499. work_restart[i].restart = 1;
  500. }
  501. static void *longpoll_thread(void *userdata)
  502. {
  503. struct thr_info *mythr = userdata;
  504. CURL *curl = NULL;
  505. char *copy_start, *hdr_path, *lp_url = NULL;
  506. bool need_slash = false;
  507. int failures = 0;
  508. hdr_path = tq_pop(mythr->q, NULL);
  509. if (!hdr_path)
  510. goto out;
  511. copy_start = (*hdr_path == '/') ? (hdr_path + 1) : hdr_path;
  512. if (rpc_url[strlen(rpc_url) - 1] != '/')
  513. need_slash = true;
  514. lp_url = malloc(strlen(rpc_url) + strlen(copy_start) + 2);
  515. if (!lp_url)
  516. goto out;
  517. sprintf(lp_url, "%s%s%s", rpc_url, need_slash ? "/" : "", copy_start);
  518. applog(LOG_INFO, "Long-polling activated for %s", lp_url);
  519. curl = curl_easy_init();
  520. if (!curl) {
  521. applog(LOG_ERR, "CURL initialization failed");
  522. goto out;
  523. }
  524. while (1) {
  525. json_t *val;
  526. val = json_rpc_call(curl, lp_url, userpass, rpc_req,
  527. false, true);
  528. if (val) {
  529. failures = 0;
  530. json_decref(val);
  531. applog(LOG_INFO, "LONGPOLL detected new block");
  532. restart_threads();
  533. } else {
  534. if (failures++ < 10) {
  535. sleep(30);
  536. applog(LOG_ERR,
  537. "longpoll failed, sleeping for 30s\n");
  538. } else {
  539. applog(LOG_ERR,
  540. "longpoll failed, ending thread\n");
  541. goto out;
  542. }
  543. }
  544. }
  545. out:
  546. free(hdr_path);
  547. free(lp_url);
  548. tq_freeze(mythr->q);
  549. if (curl)
  550. curl_easy_cleanup(curl);
  551. return NULL;
  552. }
  553. static void show_usage(void)
  554. {
  555. int i;
  556. printf("minerd version %s\n\n", VERSION);
  557. printf("Usage:\tminerd [options]\n\nSupported options:\n");
  558. for (i = 0; i < ARRAY_SIZE(options_help); i++) {
  559. struct option_help *h;
  560. h = &options_help[i];
  561. printf("--%s\n%s\n\n", h->name, h->helptext);
  562. }
  563. exit(1);
  564. }
  565. static void parse_arg (int key, char *arg)
  566. {
  567. int v, i;
  568. switch(key) {
  569. case 'a':
  570. for (i = 0; i < ARRAY_SIZE(algo_names); i++) {
  571. if (algo_names[i] &&
  572. !strcmp(arg, algo_names[i])) {
  573. opt_algo = i;
  574. break;
  575. }
  576. }
  577. if (i == ARRAY_SIZE(algo_names))
  578. show_usage();
  579. break;
  580. case 'c': {
  581. json_error_t err;
  582. if (opt_config)
  583. json_decref(opt_config);
  584. opt_config = json_load_file(arg, &err);
  585. if (!json_is_object(opt_config)) {
  586. applog(LOG_ERR, "JSON decode of %s failed", arg);
  587. show_usage();
  588. }
  589. break;
  590. }
  591. case 'q':
  592. opt_quiet = true;
  593. break;
  594. case 'D':
  595. opt_debug = true;
  596. break;
  597. case 'P':
  598. opt_protocol = true;
  599. break;
  600. case 'r':
  601. v = atoi(arg);
  602. if (v < -1 || v > 9999) /* sanity check */
  603. show_usage();
  604. opt_retries = v;
  605. break;
  606. case 'R':
  607. v = atoi(arg);
  608. if (v < 1 || v > 9999) /* sanity check */
  609. show_usage();
  610. opt_fail_pause = v;
  611. break;
  612. case 's':
  613. v = atoi(arg);
  614. if (v < 1 || v > 9999) /* sanity check */
  615. show_usage();
  616. opt_scantime = v;
  617. break;
  618. case 't':
  619. v = atoi(arg);
  620. if (v < 1 || v > 9999) /* sanity check */
  621. show_usage();
  622. opt_n_threads = v;
  623. break;
  624. case 1001: /* --url */
  625. if (strncmp(arg, "http://", 7) &&
  626. strncmp(arg, "https://", 8))
  627. show_usage();
  628. free(rpc_url);
  629. rpc_url = strdup(arg);
  630. break;
  631. case 1002: /* --userpass */
  632. if (!strchr(arg, ':'))
  633. show_usage();
  634. free(userpass);
  635. userpass = strdup(arg);
  636. break;
  637. case 1003:
  638. want_longpoll = false;
  639. break;
  640. case 1004:
  641. use_syslog = true;
  642. break;
  643. default:
  644. show_usage();
  645. }
  646. }
  647. static void parse_config(void)
  648. {
  649. int i;
  650. json_t *val;
  651. if (!json_is_object(opt_config))
  652. return;
  653. for (i = 0; i < ARRAY_SIZE(options); i++) {
  654. if (!options[i].name)
  655. break;
  656. if (!strcmp(options[i].name, "config"))
  657. continue;
  658. val = json_object_get(opt_config, options[i].name);
  659. if (!val)
  660. continue;
  661. if (options[i].has_arg && json_is_string(val)) {
  662. char *s = strdup(json_string_value(val));
  663. if (!s)
  664. break;
  665. parse_arg(options[i].val, s);
  666. free(s);
  667. } else if (!options[i].has_arg && json_is_true(val))
  668. parse_arg(options[i].val, "");
  669. else
  670. applog(LOG_ERR, "JSON option %s invalid",
  671. options[i].name);
  672. }
  673. }
  674. static void parse_cmdline(int argc, char *argv[])
  675. {
  676. int key;
  677. while (1) {
  678. key = getopt_long(argc, argv, "a:c:qDPr:s:t:h?", options, NULL);
  679. if (key < 0)
  680. break;
  681. parse_arg(key, optarg);
  682. }
  683. parse_config();
  684. }
  685. int main (int argc, char *argv[])
  686. {
  687. struct thr_info *thr;
  688. int i;
  689. rpc_url = strdup(DEF_RPC_URL);
  690. userpass = strdup(DEF_RPC_USERPASS);
  691. /* parse command line */
  692. parse_cmdline(argc, argv);
  693. pthread_mutex_init(&time_lock, NULL);
  694. #ifdef HAVE_SYSLOG_H
  695. if (use_syslog)
  696. openlog("cpuminer", LOG_PID, LOG_USER);
  697. #endif
  698. /* set our priority to the highest (aka "nicest, least intrusive") */
  699. if (setpriority(PRIO_PROCESS, 0, 19))
  700. perror("setpriority");
  701. work_restart = calloc(opt_n_threads, sizeof(*work_restart));
  702. if (!work_restart)
  703. return 1;
  704. thr_info = calloc(opt_n_threads + 2, sizeof(*thr));
  705. if (!thr_info)
  706. return 1;
  707. /* init workio thread info */
  708. work_thr_id = opt_n_threads;
  709. thr = &thr_info[work_thr_id];
  710. thr->id = work_thr_id;
  711. thr->q = tq_new();
  712. if (!thr->q)
  713. return 1;
  714. /* start work I/O thread */
  715. if (pthread_create(&thr->pth, NULL, workio_thread, thr)) {
  716. applog(LOG_ERR, "workio thread create failed");
  717. return 1;
  718. }
  719. /* init longpoll thread info */
  720. if (want_longpoll) {
  721. longpoll_thr_id = opt_n_threads + 1;
  722. thr = &thr_info[longpoll_thr_id];
  723. thr->id = longpoll_thr_id;
  724. thr->q = tq_new();
  725. if (!thr->q)
  726. return 1;
  727. /* start longpoll thread */
  728. if (pthread_create(&thr->pth, NULL, longpoll_thread, thr)) {
  729. applog(LOG_ERR, "longpoll thread create failed");
  730. return 1;
  731. }
  732. } else
  733. longpoll_thr_id = -1;
  734. /* start mining threads */
  735. for (i = 0; i < opt_n_threads; i++) {
  736. thr = &thr_info[i];
  737. thr->id = i;
  738. thr->q = tq_new();
  739. if (!thr->q)
  740. return 1;
  741. if (pthread_create(&thr->pth, NULL, miner_thread, thr)) {
  742. applog(LOG_ERR, "thread %d create failed", i);
  743. return 1;
  744. }
  745. sleep(1); /* don't pound RPC server all at once */
  746. }
  747. applog(LOG_INFO, "%d miner threads started, "
  748. "using SHA256 '%s' algorithm.\n",
  749. opt_n_threads,
  750. algo_names[opt_algo]);
  751. /* main loop - simply wait for workio thread to exit */
  752. pthread_join(thr_info[work_thr_id].pth, NULL);
  753. applog(LOG_INFO, "workio thread dead, exiting.");
  754. return 0;
  755. }