cpu-miner.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. /*
  2. Copyright 2010 Jeff Garzik
  3. Distributed under the MIT/X11 software license, see
  4. http://www.opensource.org/licenses/mit-license.php
  5. */
  6. #define _GNU_SOURCE
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <stdbool.h>
  11. #include <unistd.h>
  12. #include <time.h>
  13. #include <jansson.h>
  14. #include <curl/curl.h>
  15. #include <openssl/bn.h>
  16. #include "sha256_generic.c"
  17. enum {
  18. POW_SLEEP_INTERVAL = 5,
  19. };
  20. static const bool opt_verbose = false;
  21. static const bool opt_debug = false;
  22. static const bool opt_time = true;
  23. struct data_buffer {
  24. void *buf;
  25. size_t len;
  26. };
  27. struct upload_buffer {
  28. const void *buf;
  29. size_t len;
  30. };
  31. struct work {
  32. unsigned char midstate[32];
  33. unsigned char data[128];
  34. unsigned char hash[32];
  35. unsigned char hash1[64];
  36. BIGNUM *target;
  37. };
  38. static void databuf_free(struct data_buffer *db)
  39. {
  40. if (!db)
  41. return;
  42. free(db->buf);
  43. memset(db, 0, sizeof(*db));
  44. }
  45. static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
  46. void *user_data)
  47. {
  48. struct data_buffer *db = user_data;
  49. size_t len = size * nmemb;
  50. size_t oldlen, newlen;
  51. void *newmem;
  52. static const unsigned char zero;
  53. if (opt_debug)
  54. fprintf(stderr, "DBG(%s): %p, %lu, %lu, %p\n",
  55. __func__, ptr, (unsigned long) size,
  56. (unsigned long) nmemb, user_data);
  57. oldlen = db->len;
  58. newlen = oldlen + len;
  59. newmem = realloc(db->buf, newlen + 1);
  60. if (!newmem)
  61. return 0;
  62. db->buf = newmem;
  63. db->len = newlen;
  64. memcpy(db->buf + oldlen, ptr, len);
  65. memcpy(db->buf + newlen, &zero, 1); /* null terminate */
  66. return len;
  67. }
  68. static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
  69. void *user_data)
  70. {
  71. struct upload_buffer *ub = user_data;
  72. int len = size * nmemb;
  73. if (opt_debug)
  74. fprintf(stderr, "DBG(%s): %p, %lu, %lu, %p\n",
  75. __func__, ptr, (unsigned long) size,
  76. (unsigned long) nmemb, user_data);
  77. if (len > ub->len)
  78. len = ub->len;
  79. if (len) {
  80. memcpy(ptr, ub->buf, len);
  81. ub->buf += len;
  82. ub->len -= len;
  83. }
  84. return len;
  85. }
  86. static json_t *json_rpc_call(const char *url, const char *userpass,
  87. const char *rpc_req)
  88. {
  89. CURL *curl;
  90. json_t *val;
  91. int rc;
  92. struct data_buffer all_data = { };
  93. struct upload_buffer upload_data;
  94. json_error_t err = { };
  95. struct curl_slist *headers = NULL;
  96. char len_hdr[64];
  97. curl = curl_easy_init();
  98. if (!curl)
  99. return NULL;
  100. if (opt_verbose)
  101. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  102. curl_easy_setopt(curl, CURLOPT_URL, url);
  103. curl_easy_setopt(curl, CURLOPT_ENCODING, "");
  104. curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
  105. curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
  106. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
  107. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
  108. curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
  109. curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
  110. if (userpass) {
  111. curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
  112. curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  113. }
  114. curl_easy_setopt(curl, CURLOPT_POST, 1);
  115. upload_data.buf = rpc_req;
  116. upload_data.len = strlen(rpc_req);
  117. sprintf(len_hdr, "Content-Length: %lu",
  118. (unsigned long) upload_data.len);
  119. headers = curl_slist_append(headers,
  120. "Content-type: application/json");
  121. headers = curl_slist_append(headers, len_hdr);
  122. headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
  123. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  124. rc = curl_easy_perform(curl);
  125. if (rc)
  126. goto err_out;
  127. if (opt_debug)
  128. printf("====\nSERVER RETURNS:\n%s\n====\n",
  129. (char *) all_data.buf);
  130. val = json_loads(all_data.buf, &err);
  131. if (!val) {
  132. fprintf(stderr, "JSON failed(%d): %s\n", err.line, err.text);
  133. goto err_out;
  134. }
  135. databuf_free(&all_data);
  136. curl_slist_free_all(headers);
  137. curl_easy_cleanup(curl);
  138. return val;
  139. err_out:
  140. databuf_free(&all_data);
  141. curl_slist_free_all(headers);
  142. curl_easy_cleanup(curl);
  143. return NULL;
  144. }
  145. static char *bin2hex(unsigned char *p, size_t len)
  146. {
  147. int i;
  148. char *s = malloc((len * 2) + 1);
  149. if (!s)
  150. return NULL;
  151. for (i = 0; i < len; i++)
  152. sprintf(s + (i * 2), "%02x", p[i]);
  153. return s;
  154. }
  155. static bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
  156. {
  157. while (*hexstr && len) {
  158. char hex_byte[3];
  159. unsigned int v;
  160. if (!hexstr[1]) {
  161. fprintf(stderr, "hex2bin str truncated\n");
  162. return false;
  163. }
  164. hex_byte[0] = hexstr[0];
  165. hex_byte[1] = hexstr[1];
  166. hex_byte[2] = 0;
  167. if (sscanf(hex_byte, "%x", &v) != 1) {
  168. fprintf(stderr, "hex2bin sscanf '%s' failed\n",
  169. hex_byte);
  170. return false;
  171. }
  172. *p = (unsigned char) v;
  173. p++;
  174. hexstr += 2;
  175. len--;
  176. }
  177. return (len == 0 && *hexstr == 0) ? true : false;
  178. }
  179. static bool jobj_binary(const json_t *obj, const char *key,
  180. void *buf, size_t buflen)
  181. {
  182. const char *hexstr;
  183. json_t *tmp;
  184. tmp = json_object_get(obj, key);
  185. if (!tmp) {
  186. fprintf(stderr, "JSON key '%s' not found\n", key);
  187. return false;
  188. }
  189. hexstr = json_string_value(tmp);
  190. if (!hexstr) {
  191. fprintf(stderr, "JSON key '%s' is not a string\n", key);
  192. return false;
  193. }
  194. if (!hex2bin(buf, hexstr, buflen))
  195. return false;
  196. return true;
  197. }
  198. static void work_free(struct work *work)
  199. {
  200. if (!work)
  201. return;
  202. if (work->target)
  203. BN_free(work->target);
  204. free(work);
  205. }
  206. static struct work *work_decode(const json_t *val)
  207. {
  208. struct work *work;
  209. work = calloc(1, sizeof(*work));
  210. if (!work)
  211. return NULL;
  212. if (!jobj_binary(val, "midstate",
  213. work->midstate, sizeof(work->midstate))) {
  214. fprintf(stderr, "JSON inval midstate\n");
  215. goto err_out;
  216. }
  217. if (!jobj_binary(val, "data", work->data, sizeof(work->data))) {
  218. fprintf(stderr, "JSON inval data\n");
  219. goto err_out;
  220. }
  221. if (!jobj_binary(val, "hash1", work->hash1, sizeof(work->hash1))) {
  222. fprintf(stderr, "JSON inval hash1\n");
  223. goto err_out;
  224. }
  225. if (!BN_hex2bn(&work->target,
  226. json_string_value(json_object_get(val, "target")))) {
  227. fprintf(stderr, "JSON inval target\n");
  228. goto err_out;
  229. }
  230. return work;
  231. err_out:
  232. work_free(work);
  233. return NULL;
  234. }
  235. #define ___constant_swab32(x) ((u32)( \
  236. (((u32)(x) & (u32)0x000000ffUL) << 24) | \
  237. (((u32)(x) & (u32)0x0000ff00UL) << 8) | \
  238. (((u32)(x) & (u32)0x00ff0000UL) >> 8) | \
  239. (((u32)(x) & (u32)0xff000000UL) >> 24)))
  240. static inline uint32_t swab32(uint32_t v)
  241. {
  242. return ___constant_swab32(v);
  243. }
  244. static void runhash(void *state, void *input, const void *init)
  245. {
  246. memcpy(state, init, 32);
  247. sha256_transform(state, input);
  248. }
  249. static const uint32_t init_state[8] = {
  250. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  251. 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  252. };
  253. /* suspiciously similar to ScanHash* from bitcoin */
  254. static uint32_t scanhash(unsigned char *midstate, unsigned char *data,
  255. unsigned char *hash1, unsigned char *hash)
  256. {
  257. uint32_t *hash32 = (uint32_t *) hash;
  258. uint32_t *nonce = (uint32_t *)(data + 12);
  259. uint32_t n;
  260. time_t t_start;
  261. t_start = time(NULL);
  262. while (1) {
  263. n = *nonce;
  264. n++;
  265. *nonce = n;
  266. runhash(hash1, data, midstate);
  267. runhash(hash, hash1, init_state);
  268. if (hash32[7] == 0) {
  269. if (1) {
  270. char *hexstr;
  271. hexstr = bin2hex(hash, 32);
  272. fprintf(stderr,
  273. "DBG: found zeroes in hash:\n%s\n",
  274. hexstr);
  275. free(hexstr);
  276. }
  277. return n;
  278. }
  279. if ((n & 0xffffff) == 0) {
  280. time_t t_end = time(NULL);
  281. time_t diff = t_end - t_start;
  282. long double nd = n;
  283. long double sd = diff;
  284. if (opt_time) {
  285. fprintf(stderr,
  286. "DBG: end of nonce range, %.2Lf khps\n",
  287. (nd / sd) / 1000.0);
  288. }
  289. return 0;
  290. }
  291. }
  292. }
  293. static const char *url = "http://127.0.0.1:8332/";
  294. static const char *userpass = "pretzel:smooth";
  295. static void submit_work(struct work *work, bool byte_rev)
  296. {
  297. char *hexstr = NULL, *s = NULL;
  298. json_t *val, *res;
  299. int i;
  300. unsigned char data[128];
  301. printf("PROOF OF WORK FOUND? submitting (reversed:%s)...\n",
  302. byte_rev ? "yes" : "no");
  303. if (byte_rev) {
  304. /* byte reverse data */
  305. for (i = 0; i < 128/4; i ++)
  306. ((uint32_t *)data)[i] =
  307. swab32(((uint32_t *)work->data)[i]);
  308. } else {
  309. memcpy(data, work->data, sizeof(data));
  310. }
  311. /* build hex string */
  312. hexstr = bin2hex(work->data, sizeof(work->data));
  313. if (!hexstr)
  314. goto out;
  315. /* build JSON-RPC request */
  316. if (asprintf(&s,
  317. "{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
  318. hexstr) < 0) {
  319. fprintf(stderr, "asprintf failed\n");
  320. goto out;
  321. }
  322. if (opt_debug)
  323. fprintf(stderr, "DBG: sending RPC call:\n%s", s);
  324. /* issue JSON-RPC request */
  325. val = json_rpc_call(url, userpass, s);
  326. if (!val) {
  327. fprintf(stderr, "submit_work json_rpc_call failed\n");
  328. goto out;
  329. }
  330. res = json_object_get(val, "result");
  331. printf("PROOF OF WORK RESULT: %s\n",
  332. json_is_true(res) ? "true (yay!!!)" : "false (booooo)");
  333. json_decref(val);
  334. out:
  335. free(s);
  336. free(hexstr);
  337. }
  338. static int main_loop(void)
  339. {
  340. static const char *rpc_req =
  341. "{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
  342. while (1) {
  343. json_t *val;
  344. struct work *work;
  345. uint32_t nonce;
  346. /* obtain new work from bitcoin */
  347. val = json_rpc_call(url, userpass, rpc_req);
  348. if (!val) {
  349. fprintf(stderr, "json_rpc_call failed\n");
  350. return 1;
  351. }
  352. if (opt_verbose) {
  353. char *s = json_dumps(val, JSON_INDENT(2));
  354. printf("JSON output:\n%s\n", s);
  355. free(s);
  356. }
  357. /* decode result into work state struct */
  358. work = work_decode(json_object_get(val, "result"));
  359. if (!work) {
  360. fprintf(stderr, "work decode failed\n");
  361. return 1;
  362. }
  363. json_decref(val);
  364. /* scan nonces for a proof-of-work hash */
  365. nonce = scanhash(work->midstate, work->data + 64,
  366. work->hash1, work->hash);
  367. /* if nonce found, submit work */
  368. if (nonce) {
  369. submit_work(work, false);
  370. submit_work(work, true);
  371. fprintf(stderr, "sleeping, after proof-of-work...\n");
  372. sleep(POW_SLEEP_INTERVAL);
  373. }
  374. work_free(work);
  375. }
  376. return 0;
  377. }
  378. int main (int argc, char *argv[])
  379. {
  380. return main_loop();
  381. }