cpu-miner.c 21 KB

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