cpu-miner.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6. #include <unistd.h>
  7. #include <jansson.h>
  8. #include <curl/curl.h>
  9. #include <openssl/bn.h>
  10. #include "sha256_generic.c"
  11. static const bool opt_verbose = true;
  12. static const bool opt_debug = true;
  13. struct data_buffer {
  14. void *buf;
  15. size_t len;
  16. };
  17. struct upload_buffer {
  18. const void *buf;
  19. size_t len;
  20. };
  21. struct work {
  22. unsigned char midstate[32];
  23. unsigned char data[128];
  24. unsigned char hash[64];
  25. unsigned char hash1[64];
  26. BIGNUM *target;
  27. };
  28. static void databuf_free(struct data_buffer *db)
  29. {
  30. if (!db)
  31. return;
  32. free(db->buf);
  33. memset(db, 0, sizeof(*db));
  34. }
  35. static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
  36. void *user_data)
  37. {
  38. struct data_buffer *db = user_data;
  39. size_t len = size * nmemb;
  40. size_t oldlen, newlen;
  41. void *newmem;
  42. static const unsigned char zero;
  43. if (opt_debug)
  44. fprintf(stderr, "DBG(%s): %p, %lu, %lu, %p\n",
  45. __func__, ptr, (unsigned long) size,
  46. (unsigned long) nmemb, user_data);
  47. oldlen = db->len;
  48. newlen = oldlen + len;
  49. newmem = realloc(db->buf, newlen + 1);
  50. if (!newmem)
  51. return 0;
  52. db->buf = newmem;
  53. db->len = newlen;
  54. memcpy(db->buf + oldlen, ptr, len);
  55. memcpy(db->buf + newlen, &zero, 1); /* null terminate */
  56. return len;
  57. }
  58. static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
  59. void *user_data)
  60. {
  61. struct upload_buffer *ub = user_data;
  62. int len = size * nmemb;
  63. if (opt_debug)
  64. fprintf(stderr, "DBG(%s): %p, %lu, %lu, %p\n",
  65. __func__, ptr, (unsigned long) size,
  66. (unsigned long) nmemb, user_data);
  67. if (len > ub->len)
  68. len = ub->len;
  69. if (len) {
  70. memcpy(ptr, ub->buf, len);
  71. ub->buf += len;
  72. ub->len -= len;
  73. }
  74. return len;
  75. }
  76. static json_t *json_rpc_call(const char *url, const char *userpass,
  77. const char *rpc_req)
  78. {
  79. CURL *curl;
  80. json_t *val;
  81. int rc;
  82. struct data_buffer all_data = { };
  83. struct upload_buffer upload_data;
  84. json_error_t err = { };
  85. struct curl_slist *headers = NULL;
  86. char len_hdr[64];
  87. curl = curl_easy_init();
  88. if (!curl)
  89. return NULL;
  90. if (opt_verbose)
  91. curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  92. curl_easy_setopt(curl, CURLOPT_URL, url);
  93. curl_easy_setopt(curl, CURLOPT_ENCODING, "");
  94. curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
  95. curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
  96. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
  97. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
  98. curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
  99. curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
  100. if (userpass) {
  101. curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
  102. curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  103. }
  104. curl_easy_setopt(curl, CURLOPT_POST, 1);
  105. upload_data.buf = rpc_req;
  106. upload_data.len = strlen(rpc_req);
  107. sprintf(len_hdr, "Content-Length: %lu",
  108. (unsigned long) upload_data.len);
  109. headers = curl_slist_append(headers,
  110. "Content-type: application/json");
  111. headers = curl_slist_append(headers, len_hdr);
  112. headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
  113. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  114. rc = curl_easy_perform(curl);
  115. if (rc)
  116. goto err_out;
  117. if (opt_debug)
  118. printf("====\nSERVER RETURNS:\n%s\n====\n",
  119. (char *) all_data.buf);
  120. val = json_loads(all_data.buf, &err);
  121. if (!val) {
  122. fprintf(stderr, "JSON failed(%d): %s\n", err.line, err.text);
  123. goto err_out;
  124. }
  125. databuf_free(&all_data);
  126. curl_slist_free_all(headers);
  127. curl_easy_cleanup(curl);
  128. return val;
  129. err_out:
  130. databuf_free(&all_data);
  131. curl_slist_free_all(headers);
  132. curl_easy_cleanup(curl);
  133. return NULL;
  134. }
  135. static bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
  136. {
  137. while (*hexstr && len) {
  138. char hex_byte[3];
  139. unsigned int v;
  140. if (!hexstr[1]) {
  141. fprintf(stderr, "hex2bin str truncated\n");
  142. return false;
  143. }
  144. hex_byte[0] = hexstr[0];
  145. hex_byte[1] = hexstr[1];
  146. hex_byte[2] = 0;
  147. if (sscanf(hex_byte, "%x", &v) != 1) {
  148. fprintf(stderr, "hex2bin sscanf '%s' failed\n",
  149. hex_byte);
  150. return false;
  151. }
  152. *p = (unsigned char) v;
  153. p++;
  154. hexstr += 2;
  155. len--;
  156. }
  157. return (len == 0 && *hexstr == 0) ? true : false;
  158. }
  159. static bool jobj_binary(const json_t *obj, const char *key,
  160. void *buf, size_t buflen)
  161. {
  162. const char *hexstr;
  163. json_t *tmp;
  164. tmp = json_object_get(obj, key);
  165. if (!tmp) {
  166. fprintf(stderr, "JSON key '%s' not found\n", key);
  167. return false;
  168. }
  169. hexstr = json_string_value(tmp);
  170. if (!hexstr) {
  171. fprintf(stderr, "JSON key '%s' is not a string\n", key);
  172. return false;
  173. }
  174. if (!hex2bin(buf, hexstr, buflen))
  175. return false;
  176. return true;
  177. }
  178. static void work_free(struct work *work)
  179. {
  180. if (!work)
  181. return;
  182. if (work->target)
  183. BN_free(work->target);
  184. free(work);
  185. }
  186. static struct work *work_decode(const json_t *val)
  187. {
  188. struct work *work;
  189. work = calloc(1, sizeof(*work));
  190. if (!work)
  191. return NULL;
  192. if (!jobj_binary(val, "midstate",
  193. work->midstate, sizeof(work->midstate))) {
  194. fprintf(stderr, "JSON inval midstate\n");
  195. goto err_out;
  196. }
  197. if (!jobj_binary(val, "data", work->data, sizeof(work->data))) {
  198. fprintf(stderr, "JSON inval data\n");
  199. goto err_out;
  200. }
  201. if (!jobj_binary(val, "hash1", work->hash1, sizeof(work->hash1))) {
  202. fprintf(stderr, "JSON inval hash1\n");
  203. goto err_out;
  204. }
  205. if (!BN_hex2bn(&work->target,
  206. json_string_value(json_object_get(val, "target")))) {
  207. fprintf(stderr, "JSON inval target\n");
  208. goto err_out;
  209. }
  210. return work;
  211. err_out:
  212. work_free(work);
  213. return NULL;
  214. }
  215. static void runhash(void *state, void *input, const void *init)
  216. {
  217. memcpy(state, init, 32);
  218. sha256_transform(state, input);
  219. }
  220. static const uint32_t init_state[8] = {
  221. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
  222. 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  223. };
  224. static uint32_t scanhash(unsigned char *midstate, unsigned char *data,
  225. unsigned char *hash1, unsigned char *hash)
  226. {
  227. uint32_t *nonce = (uint32_t *)(data + 12);
  228. uint32_t n;
  229. while (1) {
  230. n = *nonce;
  231. n++;
  232. *nonce = n;
  233. runhash(hash1, data, midstate);
  234. runhash(hash, hash1, init_state);
  235. if (((uint16_t *)hash)[14] == 0) {
  236. if (opt_debug)
  237. fprintf(stderr, "DBG: found zeroes in hash\n");
  238. return n;
  239. }
  240. if ((n & 0xffffff) == 0) {
  241. if (opt_debug)
  242. fprintf(stderr, "DBG: end of nonce range\n");
  243. return 0;
  244. }
  245. }
  246. }
  247. static const char *url = "http://127.0.0.1:8332/";
  248. static const char *userpass = "pretzel:smooth";
  249. static void submit_work(struct work *work)
  250. {
  251. char hexstr[256 + 1], *s;
  252. int i;
  253. json_t *val;
  254. printf("PROOF OF WORK FOUND\n");
  255. for (i = 0; i < sizeof(work->data); i++)
  256. sprintf(hexstr + (i * 2), "%02x", work->data[i]);
  257. if (asprintf(&s,
  258. "{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
  259. hexstr) < 0) {
  260. fprintf(stderr, "asprintf failed\n");
  261. return;
  262. }
  263. if (opt_debug)
  264. fprintf(stderr, "DBG: sending RPC call:\n%s", s);
  265. val = json_rpc_call(url, userpass, s);
  266. if (!val) {
  267. fprintf(stderr, "submit_work json_rpc_call failed\n");
  268. return;
  269. }
  270. free(s);
  271. json_decref(val);
  272. }
  273. static int main_loop(void)
  274. {
  275. static const char *rpc_req =
  276. "{\"method\": \"getwork\", \"params\": [], \"id\":0}\r\n";
  277. while (1) {
  278. json_t *val;
  279. struct work *work;
  280. uint32_t nonce;
  281. val = json_rpc_call(url, userpass, rpc_req);
  282. if (!val) {
  283. fprintf(stderr, "json_rpc_call failed\n");
  284. return 1;
  285. }
  286. if (opt_verbose) {
  287. char *s = json_dumps(val, JSON_INDENT(2));
  288. printf("JSON output:\n%s\n", s);
  289. free(s);
  290. }
  291. work = work_decode(json_object_get(val, "result"));
  292. if (!work) {
  293. fprintf(stderr, "work decode failed\n");
  294. return 1;
  295. }
  296. json_decref(val);
  297. nonce = scanhash(work->midstate, work->data + 64,
  298. work->hash1, work->hash);
  299. if (nonce) {
  300. submit_work(work);
  301. fprintf(stderr, "sleeping, after proof-of-work...\n");
  302. sleep(20);
  303. }
  304. work_free(work);
  305. }
  306. return 0;
  307. }
  308. int main (int argc, char *argv[])
  309. {
  310. return main_loop();
  311. }