diff --git a/compat.h b/compat.h deleted file mode 100644 index bf488226..00000000 --- a/compat.h +++ /dev/null @@ -1,47 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __COMPAT_H__ -#define __COMPAT_H__ - -#define unlikely(expr) (__builtin_expect(!!(expr), 0)) -#define likely(expr) (__builtin_expect(!!(expr), 1)) - -#ifdef WIN32 - -#include - -#define sleep(secs) Sleep((secs) * 1000) - -enum { - PRIO_PROCESS = 0, -}; - -static inline int setpriority(int which, int who, int prio) -{ - return -!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); -} - -#endif /* WIN32 */ - -#endif /* __COMPAT_H__ */ diff --git a/elist.h b/elist.h deleted file mode 100644 index a1356184..00000000 --- a/elist.h +++ /dev/null @@ -1,274 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = (void *) 0; - entry->prev = (void *) 0; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) - -/** - * list_for_each_entry_continue - iterate over list of given type - * continuing after existing point - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_continue(pos, head, member) \ - for (pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -#endif diff --git a/stats.c b/stats.c deleted file mode 100644 index ee131672..00000000 --- a/stats.c +++ /dev/null @@ -1,137 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -#include "stats.h" -#include "options.h" -#include "utils/applog.h" -#include "persistent_memory.h" - - -static unsigned long accepted_count = 0L; -static unsigned long rejected_count = 0L; -static double *thr_hashrates; -static double *thr_times; -static uint32_t target = 0; - -pthread_mutex_t stats_lock; - - -static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); - - -/** - * @brief stats_init - */ -void stats_init() { - pthread_mutex_init(&stats_lock, NULL); - - thr_hashrates = (double *) persistent_calloc(opt_n_threads, sizeof(double)); - thr_times = (double *) persistent_calloc(opt_n_threads, sizeof(double)); -} - - - -/** - * @brief stats_set_target - * @param target - */ -void stats_set_target(uint32_t new_target) -{ - target = new_target; - - applog(LOG_DEBUG, "Pool set diff to %g", ((double) 0xffffffff) / target); -} - - -/** - * @brief stats_share_result - * @param result - */ -void stats_share_result(bool success) -{ - double hashrate = 0.0; - - pthread_mutex_lock(&stats_lock); - - for (int i = 0; i < opt_n_threads; i++) { - if (thr_times[i] > 0) { - hashrate += thr_hashrates[i] / thr_times[i]; - } - } - - success ? accepted_count++ : rejected_count++; - pthread_mutex_unlock(&stats_lock); - - applog(LOG_INFO, "accepted: %lu/%lu (%.2f%%), %.2f H/s at diff %g", - accepted_count, accepted_count + rejected_count, - 100. * accepted_count / (accepted_count + rejected_count), hashrate, - (((double) 0xffffffff) / target)); -} - - -void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done) -{ - struct timeval tv_end, diff; - - /* record scanhash elapsed time */ - gettimeofday(&tv_end, NULL); - timeval_subtract(&diff, &tv_end, tv_start); - - if (diff.tv_usec || diff.tv_sec) { - pthread_mutex_lock(&stats_lock); - thr_hashrates[thr_id] = hashes_done; - thr_times[thr_id] = (diff.tv_sec + 1e-6 * diff.tv_usec); - pthread_mutex_unlock(&stats_lock); - } -} - - -/* Subtract the `struct timeval' values X and Y, - storing the result in RESULT. - Return 1 if the difference is negative, otherwise 0. */ -static int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) -{ - /* Perform the carry for the later subtraction by updating Y. */ - if (x->tv_usec < y->tv_usec) { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - if (x->tv_usec - y->tv_usec > 1000000) { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - /* Compute the time remaining to wait. - * `tv_usec' is certainly positive. */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; -} diff --git a/stats.h b/stats.h deleted file mode 100644 index 13ec117e..00000000 --- a/stats.h +++ /dev/null @@ -1,37 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __STATS_H__ -#define __STATS_H__ - -#include -#include - - -void stats_init(); -void stats_set_target(uint32_t new_target); -void stats_share_result(bool success); -void stats_add_hashes(int thr_id, struct timeval *tv_start, unsigned long hashes_done); - - -#endif /* __STATS_H__ */ diff --git a/stratum.c b/stratum.c deleted file mode 100644 index 4e937251..00000000 --- a/stratum.c +++ /dev/null @@ -1,718 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include - -#if defined(WIN32) -# include -# include -#else -# include -# include -# include -#endif - -#ifdef __APPLE_CC__ -# include -#endif - -#include "stratum.h" -#include "version.h" -#include "stats.h" -#include "util.h" -#include "utils/applog.h" - - -#ifdef WIN32 -# define socket_blocks() (WSAGetLastError() == WSAEWOULDBLOCK) -# define poll(fdarray, nfds, timeout) WSAPoll(fdarray, nfds, timeout) -# define SHUT_RDWR SD_BOTH -#else -# define socket_blocks() (errno == EAGAIN || errno == EWOULDBLOCK) -# define closesocket(x) close((x)) -#endif - -#define RBUFSIZE 2048 -#define RECVSIZE (RBUFSIZE - 4) - -#define unlikely(expr) (__builtin_expect(!!(expr), 0)) - - -static struct work work; - - -static bool send_line(curl_socket_t sock, char *s); -static bool socket_full(curl_socket_t sock, int timeout); -static void buffer_append(struct stratum_ctx *sctx, const char *s); -static bool job(struct stratum_ctx *sctx, json_t *params); -static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose); -static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr); -static int closesocket_cb(void *clientp, curl_socket_t item); -static bool login_decode(struct stratum_ctx *sctx, const json_t *val); -static bool job_decode(const json_t *job); -static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen); - - -/** - * @brief stratum_socket_full - * @param sctx - * @param timeout - * @return - */ -bool stratum_socket_full(struct stratum_ctx *sctx, int timeout) -{ - return strlen(sctx->sockbuf) || socket_full(sctx->sock, timeout); -} - - -/** - * @brief stratum_send_line - * @param sctx - * @param s - * @return - */ -bool stratum_send_line(struct stratum_ctx *sctx, char *s) -{ - bool ret = false; - - pthread_mutex_lock(&sctx->sock_lock); - ret = send_line(sctx->sock, s); - pthread_mutex_unlock(&sctx->sock_lock); - - return ret; -} - - -/** - * @brief stratum_recv_line - * @param sctx - * @return - */ -char *stratum_recv_line(struct stratum_ctx *sctx) -{ - if (!strstr(sctx->sockbuf, "\n")) { - bool ret = true; - time_t rstart; - - time(&rstart); - - if (!socket_full(sctx->sock, 60)) { - applog(LOG_ERR, "stratum_recv_line timed out"); - return NULL; - } - - do { - char s[RBUFSIZE]; - ssize_t n; - - memset(s, 0, RBUFSIZE); - n = recv(sctx->sock, s, RECVSIZE, 0); - if (!n) { - ret = false; - break; - } - - if (n < 0) { - if (!socket_blocks() || !socket_full(sctx->sock, 1)) { - ret = false; - break; - } - } else { - buffer_append(sctx, s); - } - } while (time(NULL) - rstart < 60 && !strstr(sctx->sockbuf, "\n")); - - if (!ret) { - applog(LOG_ERR, "stratum_recv_line failed"); - return NULL; - } - } - - ssize_t buflen = strlen(sctx->sockbuf); - char *tok = strtok(sctx->sockbuf, "\n"); - - if (!tok) { - applog(LOG_ERR, "stratum_recv_line failed to parse a newline-terminated string"); - return NULL; - } - - char *sret = strdup(tok); - ssize_t len = strlen(sret); - - if (buflen > len + 1) { - memmove(sctx->sockbuf, sctx->sockbuf + len + 1, buflen - len + 1); - } - else { - sctx->sockbuf[0] = '\0'; - } - - return sret; -} - - -/** - * @brief stratum_disconnect - * @param sctx - */ -void stratum_disconnect(struct stratum_ctx *sctx) -{ - pthread_mutex_lock(&sctx->sock_lock); - - sctx->ready = false; - - if (sctx->curl) { - curl_easy_cleanup(sctx->curl); - sctx->curl = NULL; - sctx->sockbuf[0] = '\0'; - } - - pthread_mutex_unlock(&sctx->sock_lock); -} - - -/** - * @brief stratum_handle_method - * @param sctx - * @param s - * @return - */ -bool stratum_handle_method(struct stratum_ctx *sctx, const char *s) -{ - bool ret = false; - const char *method; - json_t *val = json_decode(s); - - if (!val) { - return false; - } - - if (method = json_string_value(json_object_get(val, "method"))) { - if (!strcasecmp(method, "job")) { - ret = job(sctx, json_object_get(val, "params")); - } - else { - applog(LOG_WARNING, "Unknown method: \"%s\"", method); - } - } - - json_decref(val); - return ret; -} - - -/** - * @brief stratum_handle_response - * @param buf - * @return - */ -bool stratum_handle_response(char *buf) { - bool valid = false; - - json_t *val = json_decode(buf); - if (!val) { - return false; - } - - json_t *res_val = json_object_get(val, "result"); - json_t *err_val = json_object_get(val, "error"); - json_t *id_val = json_object_get(val, "id"); - - if (!id_val || json_is_null(id_val) || !res_val) { - const char* message; - - if (json_is_object(err_val) && (message = json_string_value(json_object_get(err_val, "message")))) { - applog(LOG_ERR, "error: \"%s\"", message); - } - - json_decref(val); - return false; - } - - json_t *status = json_object_get(res_val, "status"); - - if (status && !strcmp(json_string_value(status), "KEEPALIVED") ) { - applog(LOG_DEBUG, "Keepalived receveid"); - json_decref(val); - return true; - } - - if (status) { - valid = !strcmp(json_string_value(status), "OK") && json_is_null(err_val); - } else { - valid = json_is_null(err_val); - } - - stats_share_result(valid); - json_decref(val); - return true; -} - - -/** - * @brief stratum_keepalived - * @param sctx - * @return - */ -bool stratum_keepalived(struct stratum_ctx *sctx) -{ - char *s = malloc(128); - snprintf(s, 128, "{\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"},\"id\":1}", sctx->id); - bool ret = stratum_send_line(sctx, s); - - free(s); - return ret; -} - - -/** - * @brief stratum_authorize - * @param sctx - * @param user - * @param pass - * @return - */ -bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass) -{ - char *sret; - - char *req = malloc(128 + strlen(user) + strlen(pass)); - sprintf(req, "{\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s/%s\"},\"id\":1}", user, pass, APP_NAME, APP_VERSION); - - if (!stratum_send_line(sctx, req)) { - free(req); - return false; - } - - free(req); - - while (1) { - sret = stratum_recv_line(sctx); - if (!sret) { - return false; - } - - if (!stratum_handle_method(sctx, sret)) { - break; - } - - free(sret); - } - - json_t *val = json_decode(sret); - free(sret); - - if (!val) { - return false; - } - - json_t *result = json_object_get(val, "result"); - json_t *error = json_object_get(val, "error"); - - if (!result || json_is_false(result) || (error && !json_is_null(error))) { - const char* message; - - if (json_is_object(error) && (message = json_string_value(json_object_get(error, "message")))) { - applog(LOG_ERR, "Stratum authentication failed: \"%s\"", message); - } - else { - applog(LOG_ERR, "Stratum authentication failed"); - } - - json_decref(val); - return false; - } - - if (login_decode(sctx, val) && job(sctx, json_object_get(result, "job"))) { - pthread_mutex_lock(&sctx->sock_lock); - sctx->ready = true; - pthread_mutex_unlock(&sctx->sock_lock); - } - - json_decref(val); - return true; -} - - -/** - * @brief stratum_connect - * @param sctx - * @param url - * @return - */ -bool stratum_connect(struct stratum_ctx *sctx, const char *url) -{ - CURL *curl; - - pthread_mutex_lock(&sctx->sock_lock); - sctx->ready = false; - - if (sctx->curl) { - curl_easy_cleanup(sctx->curl); - } - - sctx->curl = curl_easy_init(); - if (!sctx->curl) { - applog(LOG_ERR, "CURL initialization failed"); - pthread_mutex_unlock(&sctx->sock_lock); - return false; - } - - curl = sctx->curl; - if (!sctx->sockbuf) { - sctx->sockbuf = calloc(RBUFSIZE, 1); - sctx->sockbuf_size = RBUFSIZE; - } - - sctx->sockbuf[0] = '\0'; - pthread_mutex_unlock(&sctx->sock_lock); - - if (url != sctx->url) { - free(sctx->url); - sctx->url = strdup(url); - } - - free(sctx->curl_url); - sctx->curl_url = malloc(strlen(url)); - sprintf(sctx->curl_url, "http%s/", strstr(url, "://")); - - curl_easy_setopt(curl, CURLOPT_VERBOSE, 0); - curl_easy_setopt(curl, CURLOPT_URL, sctx->curl_url); - curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1); - curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30); - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, sctx->curl_err_str); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1); - curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_keepalive_cb); - curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket_grab_cb); - curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closesocket_cb); - curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sctx->sock); - curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1); - curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - - int rc = curl_easy_perform(curl); - if (rc) { - applog(LOG_ERR, "Stratum connection failed: code: %d, text: %s", rc, sctx->curl_err_str); - curl_easy_cleanup(curl); - sctx->curl = NULL; - return false; - } - - return true; -} - - -/** - * @brief send_line - * @param sock - * @param s - * @return - */ -static bool send_line(curl_socket_t sock, char *s) -{ - ssize_t len, sent = 0; - - len = strlen(s); - s[len++] = '\n'; - - while (len > 0) { - struct pollfd pfd; - pfd.fd = sock; - pfd.events = POLLOUT; - - if (poll(&pfd, 1, 0) < 1) { - return false; - } - - ssize_t n = send(sock, s + sent, len, 0); - if (n < 0) { - if (!socket_blocks()) { - return false; - } - - n = 0; - } - - sent += n; - len -= n; - } - - return true; -} - - -/** - * @brief socket_full - * @param sock - * @param timeout - * @return - */ -static bool socket_full(curl_socket_t sock, int timeout) -{ - struct pollfd pfd; - pfd.fd = sock; - pfd.events = POLLIN; - - return poll(&pfd, 1, timeout * 1000) > 0; -} - - -/** - * @brief buffer_append - * @param sctx - * @param s - */ -static void buffer_append(struct stratum_ctx *sctx, const char *s) -{ - size_t old, new; - - old = strlen(sctx->sockbuf); - new = old + strlen(s) + 1; - - if (new >= sctx->sockbuf_size) { - sctx->sockbuf_size = new + (RBUFSIZE - (new % RBUFSIZE)); - sctx->sockbuf = realloc(sctx->sockbuf, sctx->sockbuf_size); - } - - strcpy(sctx->sockbuf + old, s); -} - - -/** - * @brief job - * @param sctx - * @param params - * @return - */ -static bool job(struct stratum_ctx *sctx, json_t *params) -{ - if (!job_decode(params)) { - return false; - } - - pthread_mutex_lock(&sctx->work_lock); - - if (sctx->work.target != work.target) { - stats_set_target(work.target); - } - - memcpy(&sctx->work, &work, sizeof(struct work)); - pthread_mutex_unlock(&sctx->work_lock); - - return true; -} - - -/** - * @brief sockopt_keepalive_cb - * @param userdata - * @param fd - * @param purpose - * @return - */ -static int sockopt_keepalive_cb(void *userdata, curl_socket_t fd, curlsocktype purpose) -{ - int keepalive = 1; - int tcp_keepcnt = 3; - int tcp_keepidle = 50; - int tcp_keepintvl = 50; - -#ifndef WIN32 - if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) { - return 1; - } - -# ifdef __linux - if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) { - return 1; - } - - if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))) { - return 1; - } - - if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))) { - return 1; - } -# endif /* __linux */ - -# ifdef __APPLE_CC__ - if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) { - return 1; - } -# endif /* __APPLE_CC__ */ -#else /* WIN32 */ - struct tcp_keepalive vals; - vals.onoff = 1; - vals.keepalivetime = tcp_keepidle * 1000; - vals.keepaliveinterval = tcp_keepintvl * 1000; - DWORD outputBytes; - - if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) { - return 1; - } - -#endif /* WIN32 */ - - return 0; -} - - -static int closesocket_cb(void *clientp, curl_socket_t item) { - shutdown(item, SHUT_RDWR); - return closesocket(item); -} - - -/** - * @brief opensocket_grab_cb - * @param clientp - * @param purpose - * @param addr - * @return - */ -static curl_socket_t opensocket_grab_cb(void *clientp, curlsocktype purpose, struct curl_sockaddr *addr) -{ - curl_socket_t *sock = clientp; - *sock = socket(addr->family, addr->socktype, addr->protocol); - return *sock; -} - - -/** - * @brief login_decode - * @param sctx - * @param val - * @return - */ -static bool login_decode(struct stratum_ctx *sctx, const json_t *val) { - json_t *res = json_object_get(val, "result"); - if (!res) { - applog(LOG_ERR, "JSON invalid result"); - return false; - } - - const char *id = json_string_value(json_object_get(res, "id")); - if (!id || strlen(id) >= (sizeof(sctx->id))) { - applog(LOG_ERR, "JSON invalid id"); - return false; - } - - memset(&sctx->id, 0, sizeof(sctx->id)); - memcpy(&sctx->id, id, strlen(id)); - - const char *s = json_string_value(json_object_get(res, "status")); - if (!s) { - applog(LOG_ERR, "JSON invalid status"); - return false; - } - - if (strcmp(s, "OK")) { - applog(LOG_ERR, "JSON returned status \"%s\"", s); - return false; - } - - return true; -} - - -/** - * @brief job_decode - * @param sctx - * @param job - * @param work - * @return - */ -static bool job_decode(const json_t *job) { - const char *job_id = json_string_value(json_object_get(job, "job_id")); - if (!job_id || strlen(job_id) >= sizeof(work.job_id)) { - applog(LOG_ERR, "JSON invalid job id"); - return false; - } - - const char *blob = json_string_value(json_object_get(job, "blob")); - if (!blob) { - applog(LOG_ERR, "JSON invalid blob"); - return false; - } - - work.blob_size = strlen(blob); - if (work.blob_size % 2 != 0) { - applog(LOG_ERR, "JSON invalid blob length"); - return false; - } - - work.blob_size /= 2; - if (work.blob_size < 76 || work.blob_size > (sizeof(work.blob))) { - applog(LOG_ERR, "JSON invalid blob length"); - return false; - } - - if (!hex2bin((unsigned char *) work.blob, blob, work.blob_size)) { - applog(LOG_ERR, "JSON invalid blob"); - return false; - } - - jobj_binary(job, "target", &work.target, 4); - - memset(work.job_id, 0, sizeof(work.job_id)); - memcpy(work.job_id, job_id, strlen(job_id)); - - return true; -} - - -/** - * @brief jobj_binary - * @param obj - * @param key - * @param buf - * @param buflen - * @return - */ -static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen) { - const char *hexstr; - json_t *tmp; - - tmp = json_object_get(obj, key); - if (unlikely(!tmp)) { - applog(LOG_ERR, "JSON key '%s' not found", key); - return false; - } - - hexstr = json_string_value(tmp); - if (unlikely(!hexstr)) { - applog(LOG_ERR, "JSON key '%s' is not a string", key); - return false; - } - - - if (!hex2bin(buf, hexstr, buflen)) { - return false; - } - - return true; -} diff --git a/stratum.h b/stratum.h deleted file mode 100644 index 48369567..00000000 --- a/stratum.h +++ /dev/null @@ -1,78 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __STRATUM_H__ -#define __STRATUM_H__ - -#include -#include -#include - - -/** - * 128tx exploit. - * - * Max blob size is 84 (75 fixed + 9 variable), aligned to 96. - * https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. - */ -struct work { - uint32_t blob[21] __attribute__((aligned(16))); - size_t blob_size __attribute__((aligned(16))); - uint32_t target __attribute__((aligned(16))); - uint32_t hash[8] __attribute__((aligned(16))); - char job_id[64] __attribute__((aligned(16))); -}; - - -struct stratum_ctx { - char *url; - - CURL *curl; - char *curl_url; - char curl_err_str[CURL_ERROR_SIZE]; - curl_socket_t sock; - size_t sockbuf_size; - char *sockbuf; - pthread_mutex_t sock_lock; - bool ready; - - char id[64]; - - struct work work; - struct work g_work; - time_t g_work_time; - pthread_mutex_t work_lock; -}; - - -bool stratum_send_line(struct stratum_ctx *sctx, char *s); -bool stratum_socket_full(struct stratum_ctx *sctx, int timeout); -char *stratum_recv_line(struct stratum_ctx *sctx); -bool stratum_connect(struct stratum_ctx *sctx, const char *url); -void stratum_disconnect(struct stratum_ctx *sctx); -bool stratum_authorize(struct stratum_ctx *sctx, const char *user, const char *pass); -bool stratum_handle_method(struct stratum_ctx *sctx, const char *s); -bool stratum_handle_response(char *buf); -bool stratum_keepalived(struct stratum_ctx *sctx); - -#endif /* __STRATUM_H__ */ diff --git a/util.c b/util.c deleted file mode 100644 index 3dfec485..00000000 --- a/util.c +++ /dev/null @@ -1,270 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include - -#include "util.h" -#include "elist.h" -#include "utils/applog.h" - - -struct tq_ent { - void *data; - struct list_head q_node; -}; - - -struct thread_q { - struct list_head q; - bool frozen; - pthread_mutex_t mutex; - pthread_cond_t cond; -}; - - -json_t *json_decode(const char *s) -{ - json_error_t err; - json_t *val = json_loads(s, 0, &err); - - if (!val) { - applog(LOG_ERR, "JSON decode failed(%d): %s", err.line, err.text); - } - - return val; -} - - -/** - * @brief bin2hex - * @param p - * @param len - * @return - */ -char *bin2hex(const unsigned char *p, size_t len) -{ - char *s = malloc((len * 2) + 1); - if (!s) { - return NULL; - } - - for (int i = 0; i < len; i++) { - sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); - } - - return s; -} - - -/** - * @brief hex2bin - * @param p - * @param hexstr - * @param len - * @return - */ -bool hex2bin(unsigned char *p, const char *hexstr, size_t len) -{ - char hex_byte[3]; - char *ep; - - hex_byte[2] = '\0'; - - while (*hexstr && len) { - if (!hexstr[1]) { - applog(LOG_ERR, "hex2bin str truncated"); - return false; - } - - hex_byte[0] = hexstr[0]; - hex_byte[1] = hexstr[1]; - *p = (unsigned char) strtol(hex_byte, &ep, 16); - if (*ep) { - applog(LOG_ERR, "hex2bin failed on '%s'", hex_byte); - return false; - } - - p++; - hexstr += 2; - len--; - } - - return (len == 0 && *hexstr == 0) ? true : false; -} - - -/** - * @brief tq_new - * @return - */ -struct thread_q *tq_new(void) -{ - struct thread_q *tq; - - tq = calloc(1, sizeof(*tq)); - if (!tq) - return NULL; - - INIT_LIST_HEAD(&tq->q); - pthread_mutex_init(&tq->mutex, NULL); - pthread_cond_init(&tq->cond, NULL); - - return tq; -} - - -/** - * @brief tq_free - * @param tq - */ -void tq_free(struct thread_q *tq) -{ - struct tq_ent *ent, *iter; - - if (!tq) - return; - - list_for_each_entry_safe(ent, iter, &tq->q, q_node) { - list_del(&ent->q_node); - free(ent); - } - - pthread_cond_destroy(&tq->cond); - pthread_mutex_destroy(&tq->mutex); - - memset(tq, 0, sizeof(*tq)); /* poison */ - free(tq); -} - - -/** - * @brief tq_freezethaw - * @param tq - * @param frozen - */ -static void tq_freezethaw(struct thread_q *tq, bool frozen) -{ - pthread_mutex_lock(&tq->mutex); - - tq->frozen = frozen; - - pthread_cond_signal(&tq->cond); - pthread_mutex_unlock(&tq->mutex); -} - - -/** - * @brief tq_freeze - * @param tq - */ -void tq_freeze(struct thread_q *tq) -{ - tq_freezethaw(tq, true); -} - - -/** - * @brief tq_thaw - * @param tq - */ -void tq_thaw(struct thread_q *tq) -{ - tq_freezethaw(tq, false); -} - - -/** - * @brief tq_push - * @param tq - * @param data - * @return - */ -bool tq_push(struct thread_q *tq, void *data) -{ - struct tq_ent *ent; - bool rc = true; - - ent = calloc(1, sizeof(*ent)); - if (!ent) - return false; - - ent->data = data; - INIT_LIST_HEAD(&ent->q_node); - - pthread_mutex_lock(&tq->mutex); - - if (!tq->frozen) { - list_add_tail(&ent->q_node, &tq->q); - } else { - free(ent); - rc = false; - } - - pthread_cond_signal(&tq->cond); - pthread_mutex_unlock(&tq->mutex); - - return rc; -} - - -/** - * @brief tq_pop - * @param tq - * @param abstime - * @return - */ -void *tq_pop(struct thread_q *tq, const struct timespec *abstime) -{ - struct tq_ent *ent; - void *rval = NULL; - int rc; - - pthread_mutex_lock(&tq->mutex); - - if (!list_empty(&tq->q)) - goto pop; - - if (abstime) - rc = pthread_cond_timedwait(&tq->cond, &tq->mutex, abstime); - else - rc = pthread_cond_wait(&tq->cond, &tq->mutex); - if (rc) - goto out; - if (list_empty(&tq->q)) - goto out; - -pop: - ent = list_entry(tq->q.next, struct tq_ent, q_node); - rval = ent->data; - - list_del(&ent->q_node); - free(ent); - -out: - pthread_mutex_unlock(&tq->mutex); - return rval; -} diff --git a/util.h b/util.h deleted file mode 100644 index 47ab8904..00000000 --- a/util.h +++ /dev/null @@ -1,43 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __UTIL_H__ -#define __UTIL_H__ - -#include - - -json_t *json_decode(const char *s); - -char *bin2hex(const unsigned char *p, size_t len); -bool hex2bin(unsigned char *p, const char *hexstr, size_t len); - -struct thread_q *tq_new(void); -void tq_free(struct thread_q *tq); -bool tq_push(struct thread_q *tq, void *data); -void *tq_pop(struct thread_q *tq, const struct timespec *abstime); -void tq_freeze(struct thread_q *tq); -void tq_thaw(struct thread_q *tq); - - -#endif /* __UTIL_H__ */ diff --git a/xmrig.c b/xmrig.c deleted file mode 100644 index 7b14933b..00000000 --- a/xmrig.c +++ /dev/null @@ -1,677 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include - -#ifdef WIN32 -# include -# include -#endif - -#include -#include -#include - -#include "compat.h" -#include "xmrig.h" -#include "algo/cryptonight/cryptonight.h" -#include "options.h" -#include "cpu.h" -#include "persistent_memory.h" -#include "stratum.h" -#include "stats.h" -#include "util.h" -#include "utils/summary.h" -#include "utils/applog.h" - -#define LP_SCANTIME 60 -#define JSON_BUF_LEN 345 - - -struct workio_cmd { - struct thr_info *thr; - struct work *work; -}; - - -struct thr_info *thr_info; -static int work_thr_id = -1; -static int timer_thr_id = -1; -static int stratum_thr_id = -1; -struct work_restart *work_restart = NULL; -static struct stratum_ctx *stratum_ctx = NULL; -static bool backup_active = false; -static bool g_want_donate = false; - - -static void workio_cmd_free(struct workio_cmd *wc); - - -/** - * @brief work_copy - * @param dest - * @param src - */ -static inline void work_copy(struct work *dest, const struct work *src) { - memcpy(dest, src, sizeof(struct work)); -} - - -/** - * @brief restart_threads - */ -static inline void restart_threads(void) { - for (int i = 0; i < opt_n_threads; i++) { - work_restart[i].restart = 1; - } -} - - -/** - * @brief gen_workify - * @param sctx - * @param work - */ -static inline void gen_workify(struct stratum_ctx *sctx) { - pthread_mutex_lock(&stratum_ctx->work_lock); - - if (stratum_ctx->work.job_id && (!stratum_ctx->g_work_time || strcmp(stratum_ctx->work.job_id, stratum_ctx->g_work.job_id))) { - memcpy(&sctx->g_work, &sctx->work, sizeof(struct work)); - time(&stratum_ctx->g_work_time); - - pthread_mutex_unlock(&stratum_ctx->work_lock); - - applog(LOG_DEBUG, "Stratum detected new block"); - restart_threads(); - - return; - } - - pthread_mutex_unlock(&stratum_ctx->work_lock); -} - - -/** - * @brief submit_upstream_work - * @param work - * @return - */ -static bool submit_upstream_work(struct work *work) { - char s[JSON_BUF_LEN]; - - /* pass if the previous hash is not the current previous hash */ - if (memcmp(work->blob + 1, stratum_ctx->g_work.blob + 1, 32)) { - return true; - } - - char *noncestr = bin2hex(((const unsigned char*) work->blob) + 39, 4); - char *hashhex = bin2hex((const unsigned char *) work->hash, 32); - - snprintf(s, JSON_BUF_LEN, - "{\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"},\"id\":1}", - stratum_ctx->id, work->job_id, noncestr, hashhex); - - free(hashhex); - free(noncestr); - - if (unlikely(!stratum_send_line(stratum_ctx, s))) { - return false; - } - - return true; -} - - - -/** - * @brief workio_cmd_free - * @param wc - */ -static void workio_cmd_free(struct workio_cmd *wc) { - if (!wc) { - return; - } - - free(wc->work); - - memset(wc, 0, sizeof(*wc)); /* poison */ - free(wc); -} - - -/** - * @brief workio_submit_work - * @param wc - * @param curl - * @return - */ -static bool workio_submit_work(struct workio_cmd *wc) { - while (!submit_upstream_work(wc->work)) { - sleep(opt_retry_pause); - } - - return true; -} - - -/** - * @brief workio_thread - * @param userdata - * @return - */ -static void *workio_thread(void *userdata) { - struct thr_info *mythr = userdata; - bool ok = true; - - while (ok) { - struct workio_cmd *wc; - - /* wait for workio_cmd sent to us, on our queue */ - wc = tq_pop(mythr->q, NULL ); - if (!wc) { - ok = false; - break; - } - - workio_submit_work(wc); - workio_cmd_free(wc); - } - - tq_freeze(mythr->q); - - return NULL ; -} - - -/** - * @brief submit_work - * @param thr - * @param work_in - * @return - */ -static bool submit_work(struct thr_info *thr, const struct work *work_in) { - struct workio_cmd *wc; - - /* fill out work request message */ - wc = calloc(1, sizeof(*wc)); - wc->work = malloc(sizeof(*work_in)); - - if (likely(wc->work)) { - wc->thr = thr; - work_copy(wc->work, work_in); - - if (likely(tq_push(thr_info[work_thr_id].q, wc))) { - return true; - } - } - - workio_cmd_free(wc); - return false; -} - - -static bool should_pause(int thr_id) { - bool ret = false; - - pthread_mutex_lock(&stratum_ctx->sock_lock); - - if (!stratum_ctx->ready) { - ret = true; - } - - pthread_mutex_unlock(&stratum_ctx->sock_lock); - - return ret; -} - - -/** - * @brief miner_thread - * @param userdata - * @return - */ -static void *miner_thread(void *userdata) { - struct thr_info *mythr = userdata; - const int thr_id = mythr->id; - struct work work = { { 0 } }; - uint32_t max_nonce; - uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20; - - struct cryptonight_ctx *persistentctx = (struct cryptonight_ctx *) create_persistent_ctx(thr_id); - - if (cpu_info.total_logical_cpus > 1 && opt_affinity != -1L) { - affine_to_cpu_mask(thr_id, (unsigned long) opt_affinity); - } - - uint32_t *nonceptr = NULL; - uint32_t hash[8] __attribute__((aligned(32))); - - while (1) { - if (should_pause(thr_id)) { - sleep(1); - continue; - } - - pthread_mutex_lock(&stratum_ctx->work_lock); - - if (memcmp(work.job_id, stratum_ctx->g_work.job_id, 64)) { - work_copy(&work, &stratum_ctx->g_work); - nonceptr = (uint32_t*) (((char*) work.blob) + 39); - - if (opt_nicehash) { - end_nonce = (*nonceptr & 0xff000000U) + (0xffffffU / opt_n_threads * (thr_id + 1) - 0x20); - *nonceptr = (*nonceptr & 0xff000000U) + (0xffffffU / opt_n_threads * thr_id); - } - else { - *nonceptr = 0xffffffffU / opt_n_threads * thr_id; - } - } - - pthread_mutex_unlock(&stratum_ctx->work_lock); - - work_restart[thr_id].restart = 0; - - if (*nonceptr + LP_SCANTIME > end_nonce) { - max_nonce = end_nonce; - } else { - max_nonce = *nonceptr + LP_SCANTIME; - } - - unsigned long hashes_done = 0; - - struct timeval tv_start; - gettimeofday(&tv_start, NULL); - - /* scan nonces for a proof-of-work hash */ - const int rc = scanhash_cryptonight(thr_id, hash, work.blob, work.blob_size, work.target, max_nonce, &hashes_done, persistentctx); - stats_add_hashes(thr_id, &tv_start, hashes_done); - - if (!rc) { - continue; - } - - memcpy(work.hash, hash, 32); - submit_work(mythr, &work); - ++(*nonceptr); - } - - tq_freeze(mythr->q); - return NULL; -} - - -/** - * @brief miner_thread_double - * @param userdata - * @return - */ -static void *miner_thread_double(void *userdata) { - struct thr_info *mythr = userdata; - const int thr_id = mythr->id; - struct work work = { { 0 } }; - uint32_t max_nonce; - uint32_t end_nonce = 0xffffffffU / opt_n_threads * (thr_id + 1) - 0x20; - - struct cryptonight_ctx *persistentctx = (struct cryptonight_ctx *) create_persistent_ctx(thr_id); - - if (cpu_info.total_logical_cpus > 1 && opt_affinity != -1L) { - affine_to_cpu_mask(thr_id, (unsigned long) opt_affinity); - } - - uint32_t *nonceptr0 = NULL; - uint32_t *nonceptr1 = NULL; - uint8_t double_hash[64]; - uint8_t double_blob[sizeof(work.blob) * 2]; - - while (1) { - if (should_pause(thr_id)) { - sleep(1); - continue; - } - - pthread_mutex_lock(&stratum_ctx->work_lock); - - if (memcmp(work.job_id, stratum_ctx->g_work.job_id, 64)) { - work_copy(&work, &stratum_ctx->g_work); - - memcpy(double_blob, work.blob, work.blob_size); - memcpy(double_blob + work.blob_size, work.blob, work.blob_size); - - nonceptr0 = (uint32_t*) (((char*) double_blob) + 39); - nonceptr1 = (uint32_t*) (((char*) double_blob) + 39 + work.blob_size); - - if (opt_nicehash) { - end_nonce = (*nonceptr0 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * (thr_id + 1) - 0x20); - *nonceptr0 = (*nonceptr0 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * thr_id); - *nonceptr1 = (*nonceptr1 & 0xff000000U) + (0xffffffU / (opt_n_threads * 2) * (thr_id + opt_n_threads)); - } - else { - *nonceptr0 = 0xffffffffU / (opt_n_threads * 2) * thr_id; - *nonceptr1 = 0xffffffffU / (opt_n_threads * 2) * (thr_id + opt_n_threads); - } - } - - pthread_mutex_unlock(&stratum_ctx->work_lock); - - work_restart[thr_id].restart = 0; - - if (*nonceptr0 + (LP_SCANTIME / 2) > end_nonce) { - max_nonce = end_nonce; - } else { - max_nonce = *nonceptr0 + (LP_SCANTIME / 2); - } - - unsigned long hashes_done = 0; - - struct timeval tv_start; - gettimeofday(&tv_start, NULL); - - /* scan nonces for a proof-of-work hash */ - const int rc = scanhash_cryptonight_double(thr_id, (uint32_t *) double_hash, double_blob, work.blob_size, work.target, max_nonce, &hashes_done, persistentctx); - stats_add_hashes(thr_id, &tv_start, hashes_done); - - if (!rc) { - continue; - } - - if (rc & 1) { - memcpy(work.hash, double_hash, 32); - memcpy(work.blob, double_blob, work.blob_size); - submit_work(mythr, &work); - } - - if (rc & 2) { - memcpy(work.hash, double_hash + 32, 32); - memcpy(work.blob, double_blob + work.blob_size, work.blob_size); - submit_work(mythr, &work); - } - - ++(*nonceptr0); - ++(*nonceptr1); - } - - tq_freeze(mythr->q); - return NULL; -} - - - -/** - * @brief stratum_thread - * @param userdata - * @return - */ -static void *timer_thread(void *userdata) { - const int max_user_time = 100 - opt_donate_level; - int user_time_remaning = max_user_time; - int donate_time_remaning = 0; - - - while (1) { - sleep(60); - - if (user_time_remaning > 0) { - if (--user_time_remaning == 0) { - g_want_donate = true; - - donate_time_remaning = opt_donate_level; - stratum_disconnect(stratum_ctx); - continue; - } - } - - if (donate_time_remaning > 0) { - if (--donate_time_remaning == 0) { - g_want_donate = false; - - user_time_remaning = max_user_time; - stratum_disconnect(stratum_ctx); - continue; - } - } - } -} - - -static void switch_stratum() { - static bool want_donate = false; - - if (g_want_donate && !want_donate) { - stratum_ctx->url = opt_algo == ALGO_CRYPTONIGHT ? "stratum+tcp://donate.xmrig.com:443" : "stratum+tcp://donate.xmrig.com:3333"; - applog(LOG_NOTICE, "Switching to dev pool"); - want_donate = true; - } - - if (!g_want_donate && want_donate) { - stratum_ctx->url = backup_active ? opt_backup_url : opt_url; - applog(LOG_NOTICE, "Switching to user pool: \"%s\"", stratum_ctx->url); - want_donate = false; - } -} - - - -/** - * @brief stratum_thread - * @param userdata - * @return - */ -static void *stratum_thread(void *userdata) { - char *s; - - stratum_ctx->url = opt_url; - stratum_ctx->ready = false; - - while (1) { - int failures = 0; - switch_stratum(); - - while (!stratum_ctx->curl) { - pthread_mutex_lock(&stratum_ctx->work_lock); - stratum_ctx->g_work_time = 0; - pthread_mutex_unlock(&stratum_ctx->work_lock); - - restart_threads(); - switch_stratum(); - - if (!stratum_connect(stratum_ctx, stratum_ctx->url) || !stratum_authorize(stratum_ctx, opt_user, opt_pass)) { - stratum_disconnect(stratum_ctx); - failures++; - - if (failures > opt_retries && opt_backup_url) { - failures = 0; - - backup_active = !backup_active; - stratum_ctx->url = backup_active ? opt_backup_url : opt_url; - sleep(opt_retry_pause); - - applog(LOG_WARNING, "Switch to: \"%s\"", stratum_ctx->url); - continue; - } - - applog(LOG_ERR, "...retry after %d seconds", opt_retry_pause); - sleep(opt_retry_pause); - } - } - - gen_workify(stratum_ctx); - - if (opt_keepalive && !stratum_socket_full(stratum_ctx, 90)) { - stratum_keepalived(stratum_ctx); - } - - if (!stratum_socket_full(stratum_ctx, 300)) { - applog(LOG_ERR, "Stratum connection timed out"); - s = NULL; - } else { - s = stratum_recv_line(stratum_ctx); - } - - if (!s) { - stratum_disconnect(stratum_ctx); - applog(LOG_ERR, "Stratum connection interrupted"); - continue; - } - - if (!stratum_handle_method(stratum_ctx, s)) { - stratum_handle_response(s); - } - - free(s); - } - - return NULL ; -} - - -/** - * @brief start work I/O thread - * @return - */ -static bool start_workio() { - work_thr_id = opt_n_threads; - - struct thr_info *thr = &thr_info[work_thr_id]; - thr->id = work_thr_id; - thr->q = tq_new(); - - if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, workio_thread, thr))) { - return false; - } - - return true; -} - - -/** - * @brief start_stratum - * @return - */ -static bool start_stratum() { - stratum_thr_id = opt_n_threads + 1; - - stratum_ctx = persistent_calloc(1, sizeof(struct stratum_ctx)); - pthread_mutex_init(&stratum_ctx->work_lock, NULL); - pthread_mutex_init(&stratum_ctx->sock_lock, NULL); - - struct thr_info *thr = &thr_info[stratum_thr_id]; - thr->id = stratum_thr_id; - thr->q = tq_new(); - - if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, stratum_thread, thr))) { - return false; - } - - tq_push(thr_info[stratum_thr_id].q, strdup(opt_url)); - return true; -} - - -/** - * @brief start_timer - * @return - */ -static bool start_timer() { - timer_thr_id = opt_n_threads + 2; - - if (opt_donate_level < 1) { - return true; - } - - struct thr_info *thr = &thr_info[timer_thr_id]; - thr->id = timer_thr_id; - thr->q = tq_new(); - - if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, timer_thread, thr))) { - return false; - } - - return true; -} - - -/** - * @brief start_mining - * @return - */ -static bool start_mining() { - for (int i = 0; i < opt_n_threads; i++) { - struct thr_info *thr = &thr_info[i]; - - thr->id = i; - thr->q = tq_new(); - - if (unlikely(!thr->q || pthread_create(&thr->pth, NULL, opt_double_hash ? miner_thread_double : miner_thread, thr))) { - applog(LOG_ERR, "thread %d create failed", i); - return false; - } - } - - return true; -} - - -/** - * @brief main - * @param argc - * @param argv - * @return - */ -int main(int argc, char *argv[]) { - applog_init(); - cpu_init(); - parse_cmdline(argc, argv); - persistent_memory_allocate(); - print_summary(); - - stats_init(); - os_specific_init(); - - work_restart = persistent_calloc(opt_n_threads, sizeof(*work_restart)); - thr_info = persistent_calloc(opt_n_threads + 3, sizeof(struct thr_info)); - - if (!start_workio()) { - applog(LOG_ERR, "workio thread create failed"); - return 1; - } - - if (!start_stratum()) { - applog(LOG_ERR, "stratum thread create failed"); - return 1; - } - - start_timer(); - - if (!start_mining()) { - return 1; - } - - pthread_join(thr_info[work_thr_id].pth, NULL); - applog(LOG_INFO, "workio thread dead, exiting."); - persistent_memory_free(); - return 0; -} - diff --git a/xmrig.h b/xmrig.h deleted file mode 100644 index 08091367..00000000 --- a/xmrig.h +++ /dev/null @@ -1,57 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2016-2017 XMRig - * - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __XMRIG_H__ -#define __XMRIG_H__ - -#include -#include -#include -#include -#include - -#define unlikely(expr) (__builtin_expect(!!(expr), 0)) -#define likely(expr) (__builtin_expect(!!(expr), 1)) - - -struct thr_info { - int id; - pthread_t pth; - struct thread_q *q; -}; - - -struct work_restart { - volatile unsigned long restart; - char padding[128 - sizeof(unsigned long)]; -}; - - -struct work; - - -extern struct thr_info *thr_info; -extern struct work_restart *work_restart; -extern void os_specific_init(); - -#endif /* __XMRIG_H__ */