Merge branch 'dev'

This commit is contained in:
Jethro Grassie 2019-05-04 14:05:17 -04:00
commit 0467db62b5
No known key found for this signature in database
GPG key ID: DE8ED755616565BB
9 changed files with 147 additions and 157 deletions

View file

@ -37,7 +37,7 @@ endif
ifeq ($(OS),Darwin) ifeq ($(OS),Darwin)
LDPARAM = LDPARAM =
else else
LDPARAM = -rdynamic -Wl,-warn-unresolved-symbols -fPIC -pie LDPARAM = -Wl,-warn-unresolved-symbols -fPIC -pie
endif endif
ifeq ($(TYPE),debug) ifeq ($(TYPE),debug)
@ -48,7 +48,7 @@ endif
ifeq ($(TYPE), release) ifeq ($(TYPE), release)
CCPARAM += -O3 -Wno-unused-variable CCPARAM += -O3 -Wno-unused-variable
ifneq ($(OS), Darwin) ifneq ($(OS), Darwin)
LDPARAM = -rdynamic -Wl,--unresolved-symbols=ignore-in-object-files LDPARAM = -Wl,--unresolved-symbols=ignore-in-object-files
endif endif
endif endif
@ -56,13 +56,13 @@ LDPARAM += $(LDFLAGS)
LIBS := lmdb pthread microhttpd unbound LIBS := lmdb pthread microhttpd unbound
ifeq ($(OS), Darwin) ifeq ($(OS), Darwin)
LIBS += c++ boost_system-mt boost_date_time-mt boost_chrono-mt boost_filesystem-mt boost_thread-mt LIBS += c++ boost_system-mt boost_date_time-mt boost_chrono-mt boost_filesystem-mt boost_thread-mt boost_regex-mt
else else
LIBS += dl boost_system boost_date_time boost_chrono boost_filesystem boost_thread uuid LIBS += dl boost_system boost_date_time boost_chrono boost_filesystem boost_thread boost_regex uuid
endif endif
PKG_LIBS := $(shell pkg-config \ PKG_LIBS := $(shell pkg-config \
libevent \ "libevent >= 2.1" \
json-c \ json-c \
openssl \ openssl \
libsodium \ libsodium \
@ -74,7 +74,7 @@ DLIBS =
INCPATH := $(DIRS) ${MONERO_INC} /opt/local/include /usr/local/include INCPATH := $(DIRS) ${MONERO_INC} /opt/local/include /usr/local/include
PKG_INC := $(shell pkg-config \ PKG_INC := $(shell pkg-config \
libevent \ "libevent >= 2.1" \
json-c \ json-c \
openssl \ openssl \
libsodium \ libsodium \
@ -87,6 +87,7 @@ EXTRA_FILES = Makefile
C++ = g++ C++ = g++
CC = gcc CC = gcc
XXD := $(shell command -v xxd)
STORE = build/$(TYPE) STORE = build/$(TYPE)
SOURCE := $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp)) SOURCE := $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp))
@ -163,6 +164,12 @@ endif
ifeq ($(origin MONERO_BUILD_ROOT), undefined) ifeq ($(origin MONERO_BUILD_ROOT), undefined)
$(error You need to set an environment variable MONERO_BUILD_ROOT to your monero build root) $(error You need to set an environment variable MONERO_BUILD_ROOT to your monero build root)
endif endif
ifndef PKG_LIBS
$(error Missing dependencies)
endif
ifndef XXD
$(error Command xxd not found)
endif
-include $(DFILES) -include $(DFILES)
-include $(CDFILES) -include $(CDFILES)

View file

@ -68,7 +68,9 @@
#define MAX_LINE 4096 #define MAX_LINE 4096
#define POOL_CLIENTS_GROW 1024 #define POOL_CLIENTS_GROW 1024
#define RPC_BODY_MAX 4096 #define RPC_BODY_MAX 4096
#define CLIENT_BODY_MAX 2048 #define JOB_BODY_MAX 2048
#define ERROR_BODY_MAX 512
#define STATUS_BODY_MAX 256
#define CLIENT_JOBS_MAX 4 #define CLIENT_JOBS_MAX 4
#define BLOCK_HEADERS_MAX 4 #define BLOCK_HEADERS_MAX 4
#define BLOCK_TEMPLATES_MAX 4 #define BLOCK_TEMPLATES_MAX 4
@ -222,13 +224,11 @@ static void pool_clients_init();
static void pool_clients_free(); static void pool_clients_free();
static void pool_clients_send_job(); static void pool_clients_send_job();
static void target_to_hex(uint64_t target, char *target_hex); static void target_to_hex(uint64_t target, char *target_hex);
static char * stratum_new_proxy_job_body(int json_id, const char *client_id, const char *job_id, static void stratum_get_proxy_job_body(char *body, const client_t *client,
const block_template_t *block_template, const char *template_blob, const char *block_hex, bool response);
uint64_t target, bool response); static void stratum_get_job_body(char *body, const client_t *client, bool response);
static char * stratum_new_job_body(int json_id, const char *client_id, const char *job_id, static inline void stratum_get_error_body(char *body, int json_id, const char *error);
const char *blob, uint64_t target, uint64_t height, bool response); static inline void stratum_get_status_body(char *body, int json_id, const char *status);
static char * stratum_new_error_body(int json_id, const char *error);
static char * stratum_new_status_body(int json_id, const char *status);
static void client_add(int fd, struct bufferevent *bev); static void client_add(int fd, struct bufferevent *bev);
static void client_find(struct bufferevent *bev, client_t **client); static void client_find(struct bufferevent *bev, client_t **client);
static void client_clear(struct bufferevent *bev); static void client_clear(struct bufferevent *bev);
@ -237,7 +237,7 @@ static void client_clear_jobs(client_t *client);
static job_t * client_find_job(client_t *client, const char *job_id); static job_t * client_find_job(client_t *client, const char *job_id);
static void response_to_block_template(json_object *result, block_template_t *block_template); static void response_to_block_template(json_object *result, block_template_t *block_template);
static void response_to_block(json_object *block_header, block_t *block); static void response_to_block(json_object *block_header, block_t *block);
static char * rpc_new_request_body(const char* method, char* fmt, ...); static void rpc_get_request_body(char *body, const char* method, char* fmt, ...);
static void rpc_on_response(struct evhttp_request *req, void *arg); static void rpc_on_response(struct evhttp_request *req, void *arg);
static void rpc_request(struct event_base *base, const char *body, rpc_callback_t *callback); static void rpc_request(struct event_base *base, const char *body, rpc_callback_t *callback);
static void rpc_wallet_request(struct event_base *base, const char *body, rpc_callback_t *callback); static void rpc_wallet_request(struct event_base *base, const char *body, rpc_callback_t *callback);
@ -869,11 +869,11 @@ startup_pauout(uint64_t height)
if (block->status & BLOCK_UNLOCKED || block->status & BLOCK_ORPHANED) if (block->status & BLOCK_UNLOCKED || block->status & BLOCK_ORPHANED)
continue; continue;
char *body = rpc_new_request_body("get_block_header_by_height", "sd", "height", block->height); char body[RPC_BODY_MAX];
rpc_get_request_body(body, "get_block_header_by_height", "sd", "height", block->height);
rpc_callback_t *c = calloc(1, sizeof(rpc_callback_t)); rpc_callback_t *c = calloc(1, sizeof(rpc_callback_t));
c->cb = rpc_on_block_header_by_height; c->cb = rpc_on_block_header_by_height;
rpc_request(base, body, c); rpc_request(base, body, c);
free(body);
} }
mdb_cursor_close(cursor); mdb_cursor_close(cursor);
@ -910,8 +910,7 @@ block_template_free(block_template_t *block_template)
static void static void
block_templates_free() block_templates_free()
{ {
size_t length = sizeof(last_block_headers)/sizeof(*last_block_headers); for (size_t i=0; i<BLOCK_TEMPLATES_MAX; i++)
for (size_t i=0; i<length; i++)
{ {
block_template_t *bt = block_templates[i]; block_template_t *bt = block_templates[i];
if (bt != NULL) if (bt != NULL)
@ -926,8 +925,7 @@ block_templates_free()
static void static void
last_block_headers_free() last_block_headers_free()
{ {
size_t length = sizeof(last_block_headers)/sizeof(*last_block_headers); for (size_t i=0; i<BLOCK_HEADERS_MAX; i++)
for (size_t i=0; i<length; i++)
{ {
block_t *block = last_block_headers[i]; block_t *block = last_block_headers[i];
if (block != NULL) if (block != NULL)
@ -1011,83 +1009,83 @@ target_to_hex(uint64_t target, char *target_hex)
BN_free(diff); BN_free(diff);
} }
static char * static void
stratum_new_proxy_job_body(int json_id, const char *client_id, const char *job_id, stratum_get_proxy_job_body(char *body, const client_t *client, const char *block_hex, bool response)
const block_template_t *block_template, const char *template_blob,
uint64_t target, bool response)
{ {
char *body = calloc(CLIENT_BODY_MAX, sizeof(char)); int json_id = client->json_id;
const char *client_id = client->client_id;
const job_t *job = &client->active_jobs[0];
char job_id[33];
bin_to_hex((const char*)job->id, sizeof(uuid_t), job_id);
uint64_t target = job->target;
char target_hex[17]; char target_hex[17];
target_to_hex(target, &target_hex[0]); target_to_hex(target, &target_hex[0]);
const block_template_t *bt = job->block_template;
const block_template_t *bt = block_template;
if (response) if (response)
{ {
snprintf(body, CLIENT_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\"" snprintf(body, JOB_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\""
":{\"id\":\"%.32s\",\"job\":{\"blocktemplate_blob\":\"%s\",\"job_id\":\"%.32s\"," ":{\"id\":\"%.32s\",\"job\":{\"blocktemplate_blob\":\"%s\",\"job_id\":\"%.32s\","
"\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u," "\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u,"
"\"client_pool_offset\":%u,\"target_diff\":%"PRIu64",\"target_diff_hex\":\"%s\"}," "\"client_pool_offset\":%u,\"target_diff\":%"PRIu64",\"target_diff_hex\":\"%s\"},"
"\"status\":\"OK\"}}\n", json_id, client_id, template_blob, job_id, "\"status\":\"OK\"}}\n", json_id, client_id, block_hex, job_id,
bt->difficulty, bt->height, bt->reserved_offset, bt->reserved_offset + 12, bt->difficulty, bt->height, bt->reserved_offset, bt->reserved_offset + 12,
bt->reserved_offset + 8, target, target_hex); bt->reserved_offset + 8, target, target_hex);
} }
else else
{ {
snprintf(body, CLIENT_BODY_MAX, "{\"jsonrpc\":\"2.0\",\"method\":\"job\",\"params\"" snprintf(body, JOB_BODY_MAX, "{\"jsonrpc\":\"2.0\",\"method\":\"job\",\"params\""
":{\"id\":\"%.32s\",\"job\":{\"blocktemplate_blob\":\"%s\",\"job_id\":\"%.32s\"," ":{\"id\":\"%.32s\",\"job\":{\"blocktemplate_blob\":\"%s\",\"job_id\":\"%.32s\","
"\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u," "\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u,"
"\"client_pool_offset\":%u,\"target_diff\":%"PRIu64",\"target_diff_hex\":\"%s\"}," "\"client_pool_offset\":%u,\"target_diff\":%"PRIu64",\"target_diff_hex\":\"%s\"},"
"\"status\":\"OK\"}}\n", client_id, template_blob, job_id, "\"status\":\"OK\"}}\n", client_id, block_hex, job_id,
bt->difficulty, bt->height, bt->reserved_offset, bt->reserved_offset + 12, bt->difficulty, bt->height, bt->reserved_offset, bt->reserved_offset + 12,
bt->reserved_offset + 8, target, target_hex); bt->reserved_offset + 8, target, target_hex);
} }
return body;
} }
static char * static void
stratum_new_job_body(int json_id, const char *client_id, const char *job_id, stratum_get_job_body(char *body, const client_t *client, bool response)
const char *blob, uint64_t target, uint64_t height, bool response)
{ {
char *body = calloc(CLIENT_BODY_MAX, sizeof(char)); int json_id = client->json_id;
const char *client_id = client->client_id;
const job_t *job = &client->active_jobs[0];
char job_id[33];
bin_to_hex((const char*)job->id, sizeof(uuid_t), job_id);
const char *blob = job->blob;
uint64_t target = job->target;
uint64_t height = job->block_template->height;
char target_hex[17]; char target_hex[17];
target_to_hex(target, &target_hex[0]); target_to_hex(target, &target_hex[0]);
if (response) if (response)
{ {
snprintf(body, CLIENT_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\"" snprintf(body, JOB_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\""
":{\"id\":\"%.32s\",\"job\":{" ":{\"id\":\"%.32s\",\"job\":{"
"\"blob\":\"%s\",\"job_id\":\"%.32s\",\"target\":\"%s\",\"height\":%"PRIu64"}," "\"blob\":\"%s\",\"job_id\":\"%.32s\",\"target\":\"%s\",\"height\":%"PRIu64"},"
"\"status\":\"OK\"}}\n", json_id, client_id, blob, job_id, target_hex, height); "\"status\":\"OK\"}}\n", json_id, client_id, blob, job_id, target_hex, height);
} }
else else
{ {
snprintf(body, CLIENT_BODY_MAX, "{\"jsonrpc\":\"2.0\",\"method\":\"job\",\"params\"" snprintf(body, JOB_BODY_MAX, "{\"jsonrpc\":\"2.0\",\"method\":\"job\",\"params\""
":{\"id\":\"%.32s\",\"blob\":\"%s\",\"job_id\":\"%.32s\",\"target\":\"%s\"," ":{\"id\":\"%.32s\",\"blob\":\"%s\",\"job_id\":\"%.32s\",\"target\":\"%s\","
"\"height\":%"PRIu64"}}\n", "\"height\":%"PRIu64"}}\n",
client_id, blob, job_id, target_hex, height); client_id, blob, job_id, target_hex, height);
} }
return body;
} }
static char * static inline void
stratum_new_error_body(int json_id, const char *error) stratum_get_error_body(char *body, int json_id, const char *error)
{ {
char *body = calloc(512, sizeof(char)); snprintf(body, ERROR_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":"
snprintf(body, 512, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":"
"{\"code\":-1, \"message\":\"%s\"}}\n", json_id, error); "{\"code\":-1, \"message\":\"%s\"}}\n", json_id, error);
return body;
} }
static char * static inline void
stratum_new_status_body(int json_id, const char *status) stratum_get_status_body(char *body, int json_id, const char *status)
{ {
char *body = calloc(256, sizeof(char)); snprintf(body, STATUS_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\":{\"status\":\"%s\"}}\n",
snprintf(body, 256, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\":{\"status\":\"%s\"}}\n",
json_id, status); json_id, status);
return body;
} }
static void static void
@ -1128,21 +1126,20 @@ response_to_block(json_object *block_header, block_t *block)
block->status |= BLOCK_ORPHANED; block->status |= BLOCK_ORPHANED;
} }
static char * static void
rpc_new_request_body(const char* method, char* fmt, ...) rpc_get_request_body(char *body, const char* method, char* fmt, ...)
{ {
char *result = calloc(RPC_BODY_MAX, sizeof(char)); char *pb = body;
char *pr = &result[0];
snprintf(pr, RPC_BODY_MAX, "%s%s%s", "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"", method, "\""); snprintf(pb, RPC_BODY_MAX, "%s%s%s", "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"", method, "\"");
pr += strlen(pr); pb += strlen(pb);
if (fmt && *fmt) if (fmt && *fmt)
{ {
char *s; char *s;
uint64_t d; uint64_t d;
snprintf(pr, RPC_BODY_MAX - strlen(result), "%s", ",\"params\":{"); snprintf(pb, RPC_BODY_MAX - strlen(body), "%s", ",\"params\":{");
pr += strlen(pr); pb += strlen(pb);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
uint8_t count = 0; uint8_t count = 0;
@ -1152,27 +1149,26 @@ rpc_new_request_body(const char* method, char* fmt, ...)
{ {
case 's': case 's':
s = va_arg(args, char *); s = va_arg(args, char *);
snprintf(pr, RPC_BODY_MAX - strlen(result), "\"%s\"", s); snprintf(pb, RPC_BODY_MAX - strlen(body), "\"%s\"", s);
pr += strlen(pr); pb += strlen(pb);
break; break;
case 'd': case 'd':
d = va_arg(args, uint64_t); d = va_arg(args, uint64_t);
snprintf(pr, RPC_BODY_MAX - strlen(result), "%"PRIu64, d); snprintf(pb, RPC_BODY_MAX - strlen(body), "%"PRIu64, d);
pr += strlen(pr); pb += strlen(pb);
break; break;
} }
char append = ':'; char append = ':';
if (count++ % 2 != 0) if (count++ % 2 != 0)
append = ','; append = ',';
*pr++ = append; *pb++ = append;
} }
va_end(args); va_end(args);
*--pr = '}'; *--pb = '}';
pr++; pb++;
} }
*pr = '}'; *pb = '}';
log_trace("Payload: %s", result); log_trace("Payload: %s", body);
return result;
} }
static void static void
@ -1184,22 +1180,23 @@ rpc_on_response(struct evhttp_request *req, void *arg)
if (!req) if (!req)
{ {
log_error("Request failure. Aborting."); log_error("Request failure. Aborting.");
return; goto cleanup;
} }
int rc = evhttp_request_get_response_code(req); int rc = evhttp_request_get_response_code(req);
if (rc < 200 || rc >= 300) if (rc < 200 || rc >= 300)
{ {
log_error("HTTP status code %d for %s. Aborting.", rc, evhttp_request_get_uri(req)); log_error("HTTP status code %d for %s. Aborting.", rc, evhttp_request_get_uri(req));
return; goto cleanup;
} }
input = evhttp_request_get_input_buffer(req); input = evhttp_request_get_input_buffer(req);
size_t len = evbuffer_get_length(input); size_t len = evbuffer_get_length(input);
char data[len+1]; char *data = (char*) alloca(len+1);
evbuffer_remove(input, data, len); evbuffer_remove(input, data, len);
data[len] = '\0'; data[len] = '\0';
callback->cb(&data[0], callback); callback->cb(data, callback);
cleanup:
if (callback->data) if (callback->data)
free(callback->data); free(callback->data);
free(callback); free(callback);
@ -1214,6 +1211,7 @@ rpc_request(struct event_base *base, const char *body, rpc_callback_t *callback)
struct evbuffer *output; struct evbuffer *output;
con = evhttp_connection_base_new(base, NULL, config.rpc_host, config.rpc_port); con = evhttp_connection_base_new(base, NULL, config.rpc_host, config.rpc_port);
evhttp_connection_free_on_completion(con);
evhttp_connection_set_timeout(con, config.rpc_timeout); evhttp_connection_set_timeout(con, config.rpc_timeout);
req = evhttp_request_new(rpc_on_response, callback); req = evhttp_request_new(rpc_on_response, callback);
output = evhttp_request_get_output_buffer(req); output = evhttp_request_get_output_buffer(req);
@ -1233,6 +1231,7 @@ rpc_wallet_request(struct event_base *base, const char *body, rpc_callback_t *ca
struct evbuffer *output; struct evbuffer *output;
con = evhttp_connection_base_new(base, NULL, config.wallet_rpc_host, config.wallet_rpc_port); con = evhttp_connection_base_new(base, NULL, config.wallet_rpc_host, config.wallet_rpc_port);
evhttp_connection_free_on_completion(con);
evhttp_connection_set_timeout(con, config.rpc_timeout); evhttp_connection_set_timeout(con, config.rpc_timeout);
req = evhttp_request_new(rpc_on_response, callback); req = evhttp_request_new(rpc_on_response, callback);
output = evhttp_request_get_output_buffer(req); output = evhttp_request_get_output_buffer(req);
@ -1271,6 +1270,7 @@ rpc_on_block_headers_range(const char* data, rpc_callback_t *callback)
JSON_GET_OR_WARN(headers, result, json_type_array); JSON_GET_OR_WARN(headers, result, json_type_array);
size_t headers_len = json_object_array_length(headers); size_t headers_len = json_object_array_length(headers);
assert(headers_len == BLOCK_HEADERS_RANGE);
for (int i=0; i<headers_len; i++) for (int i=0; i<headers_len; i++)
{ {
json_object *header = json_object_array_get_idx(headers, i); json_object *header = json_object_array_get_idx(headers, i);
@ -1424,24 +1424,25 @@ rpc_on_last_block_header(const char* data, rpc_callback_t *callback)
pool_stats.network_difficulty = last_block_headers[0]->difficulty; pool_stats.network_difficulty = last_block_headers[0]->difficulty;
pool_stats.network_hashrate = last_block_headers[0]->difficulty / BLOCK_TIME; pool_stats.network_hashrate = last_block_headers[0]->difficulty / BLOCK_TIME;
pool_stats.network_height = last_block_headers[0]->height;
update_pool_hr(); update_pool_hr();
if (need_new_template) if (need_new_template)
{ {
log_info("Fetching new block template"); log_info("Fetching new block template");
char *body = rpc_new_request_body("get_block_template", "sssd", "wallet_address", config.pool_wallet, "reserve_size", 17); char body[RPC_BODY_MAX];
uint64_t reserve = 17;
rpc_get_request_body(body, "get_block_template", "sssd", "wallet_address", config.pool_wallet, "reserve_size", reserve);
rpc_callback_t *c1 = calloc(1, sizeof(rpc_callback_t)); rpc_callback_t *c1 = calloc(1, sizeof(rpc_callback_t));
c1->cb = rpc_on_block_template; c1->cb = rpc_on_block_template;
rpc_request(base, body, c1); rpc_request(base, body, c1);
free(body);
uint32_t end = block->height - 60; uint64_t end = block->height - 60;
uint32_t start = end - BLOCK_HEADERS_RANGE + 1; uint64_t start = end - BLOCK_HEADERS_RANGE + 1;
body = rpc_new_request_body("get_block_headers_range", "sdsd", "start_height", start, "end_height", end); rpc_get_request_body(body, "get_block_headers_range", "sdsd", "start_height", start, "end_height", end);
rpc_callback_t *c2 = calloc(1, sizeof(rpc_callback_t)); rpc_callback_t *c2 = calloc(1, sizeof(rpc_callback_t));
c2->cb = rpc_on_block_headers_range; c2->cb = rpc_on_block_headers_range;
rpc_request(base, body, c2); rpc_request(base, body, c2);
free(body);
} }
json_object_put(root); json_object_put(root);
@ -1591,11 +1592,11 @@ static void
timer_on_120s(int fd, short kind, void *ctx) timer_on_120s(int fd, short kind, void *ctx)
{ {
log_info("Fetching last block header"); log_info("Fetching last block header");
char *body = rpc_new_request_body("get_last_block_header", NULL); char body[RPC_BODY_MAX];
rpc_get_request_body(body, "get_last_block_header", NULL);
rpc_callback_t *callback = calloc(1, sizeof(rpc_callback_t)); rpc_callback_t *callback = calloc(1, sizeof(rpc_callback_t));
callback->cb = rpc_on_last_block_header; callback->cb = rpc_on_last_block_header;
rpc_request(base, body, callback); rpc_request(base, body, callback);
free(body);
struct timeval timeout = { .tv_sec = 120, .tv_usec = 0 }; struct timeval timeout = { .tv_sec = 120, .tv_usec = 0 };
evtimer_add(timer_120s, &timeout); evtimer_add(timer_120s, &timeout);
} }
@ -1747,23 +1748,21 @@ client_send_job(client_t *client, bool response)
job->target = target; job->target = target;
log_debug("Client %.32s target now %"PRIu64, client->client_id, target); log_debug("Client %.32s target now %"PRIu64, client->client_id, target);
char *body; char body[JOB_BODY_MAX];
if (!client->is_proxy) if (!client->is_proxy)
{ {
body = stratum_new_job_body(client->json_id, client->client_id, job_id, stratum_get_job_body(body, client, response);
job->blob, target, bt->height, response);
} }
else else
{ {
char *template_hex = calloc(bin_size+1, sizeof(char)); char *block_hex = calloc(bin_size+1, sizeof(char));
bin_to_hex(block, bin_size, template_hex); bin_to_hex(block, bin_size, block_hex);
body = stratum_new_proxy_job_body(client->json_id, client->client_id, job_id, stratum_get_proxy_job_body(body, client, block_hex, response);
bt, template_hex, target, response); free(block_hex);
} }
log_trace("Client job: %s", body); log_trace("Client job: %s", body);
struct evbuffer *output = bufferevent_get_output(client->bev); struct evbuffer *output = bufferevent_get_output(client->bev);
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
free(body);
free(block); free(block);
free(hashing_blob); free(hashing_blob);
} }
@ -1792,10 +1791,10 @@ static void
send_validation_error(const client_t *client, const char *message) send_validation_error(const client_t *client, const char *message)
{ {
struct evbuffer *output = bufferevent_get_output(client->bev); struct evbuffer *output = bufferevent_get_output(client->bev);
char *body = stratum_new_error_body(client->json_id, message); char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, message);
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
log_debug("Validation error: %s", message); log_debug("Validation error: %s", message);
free(body);
} }
static void static void
@ -1930,10 +1929,10 @@ client_on_submit(json_object *message, client_t *client)
{ {
if (submissions[i] == sub) if (submissions[i] == sub)
{ {
char *body = stratum_new_error_body(client->json_id, "Duplicate share"); char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, "Duplicate share");
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
log_debug("Duplicate share"); log_debug("Duplicate share");
free(body);
free(block); free(block);
return; return;
} }
@ -1952,10 +1951,10 @@ client_on_submit(json_object *message, client_t *client)
char *hashing_blob = NULL; char *hashing_blob = NULL;
if (get_hashing_blob(block, bin_size, &hashing_blob, &hashing_blob_size) != 0) if (get_hashing_blob(block, bin_size, &hashing_blob, &hashing_blob_size) != 0)
{ {
char *body = stratum_new_error_body(client->json_id, "Invalid block"); char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, "Invalid block");
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
log_debug("Invalid block"); log_debug("Invalid block");
free(body);
free(block); free(block);
return; return;
} }
@ -1970,11 +1969,11 @@ client_on_submit(json_object *message, client_t *client)
if (memcmp(submitted_hash, result_hash, 32) != 0) if (memcmp(submitted_hash, result_hash, 32) != 0)
{ {
char *body = stratum_new_error_body(client->json_id, "Invalid share"); char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, "Invalid share");
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
log_debug("Invalid share"); log_debug("Invalid share");
/* TODO: record and ban if too many */ /* TODO: record and ban if too many */
free(body);
free(block); free(block);
free(hashing_blob); free(hashing_blob);
return; return;
@ -2005,9 +2004,10 @@ client_on_submit(json_object *message, client_t *client)
log_info("+++ MINED A BLOCK +++"); log_info("+++ MINED A BLOCK +++");
char *block_hex = calloc((bin_size << 1)+1, sizeof(char)); char *block_hex = calloc((bin_size << 1)+1, sizeof(char));
bin_to_hex(block, bin_size, block_hex); bin_to_hex(block, bin_size, block_hex);
char *body = calloc(RPC_BODY_MAX, sizeof(char)); char body[RPC_BODY_MAX];
snprintf(body, RPC_BODY_MAX, snprintf(body, RPC_BODY_MAX,
"{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_block\", \"params\":[\"%s\"]}", block_hex); "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"submit_block\", \"params\":[\"%s\"]}",
block_hex);
rpc_callback_t *callback = calloc(1, sizeof(rpc_callback_t)); rpc_callback_t *callback = calloc(1, sizeof(rpc_callback_t));
callback->cb = rpc_on_block_submitted; callback->cb = rpc_on_block_submitted;
@ -2022,16 +2022,15 @@ client_on_submit(json_object *message, client_t *client)
b->timestamp = now; b->timestamp = now;
rpc_request(base, body, callback); rpc_request(base, body, callback);
free(body);
free(block_hex); free(block_hex);
} }
else if (BN_cmp(hd, jd) < 0) else if (BN_cmp(hd, jd) < 0)
{ {
can_store = false; can_store = false;
char *body = stratum_new_error_body(client->json_id, "Low difficulty share"); char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, "Low difficulty share");
log_debug("Low difficulty (%lu) share", BN_get_word(jd)); log_debug("Low difficulty (%lu) share", BN_get_word(jd));
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
free(body);
} }
else else
can_store = true; can_store = true;
@ -2053,15 +2052,16 @@ client_on_submit(json_object *message, client_t *client)
int rc = store_share(share.height, &share); int rc = store_share(share.height, &share);
if (rc != 0) if (rc != 0)
log_warn("Failed to store share: %s", mdb_strerror(rc)); log_warn("Failed to store share: %s", mdb_strerror(rc));
char *body = stratum_new_status_body(client->json_id, "OK"); char body[STATUS_BODY_MAX];
stratum_get_status_body(body, client->json_id, "OK");
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
free(body);
} }
} }
static void static void
client_on_read(struct bufferevent *bev, void *ctx) client_on_read(struct bufferevent *bev, void *ctx)
{ {
const char unknown_method[] = "Unknown method";
struct evbuffer *input, *output; struct evbuffer *input, *output;
char *line; char *line;
size_t n; size_t n;
@ -2074,10 +2074,14 @@ client_on_read(struct bufferevent *bev, void *ctx)
input = bufferevent_get_input(bev); input = bufferevent_get_input(bev);
output = bufferevent_get_output(bev); output = bufferevent_get_output(bev);
if (evbuffer_get_length(input) >= MAX_LINE) size_t len = evbuffer_get_length(input);
if (len >= MAX_LINE)
{ {
const char *too_long = "Message too long\n"; const char *too_long = "Message too long\n";
evbuffer_add(output, too_long, strlen(too_long)); evbuffer_add(output, too_long, strlen(too_long));
log_info("Removing client. Message too long.");
evbuffer_drain(input, len);
client_clear(bev);
return; return;
} }
@ -2087,14 +2091,13 @@ client_on_read(struct bufferevent *bev, void *ctx)
JSON_GET_OR_WARN(method, message, json_type_string); JSON_GET_OR_WARN(method, message, json_type_string);
JSON_GET_OR_WARN(id, message, json_type_int); JSON_GET_OR_WARN(id, message, json_type_int);
const char *method_name = json_object_get_string(method); const char *method_name = json_object_get_string(method);
const char unknown[] = "Unknown method";
client->json_id = json_object_get_int(id); client->json_id = json_object_get_int(id);
bool unknown = false;
if (method_name == NULL) if (method_name == NULL)
{ {
char *body = stratum_new_error_body(client->json_id, unknown); unknown = true;
evbuffer_add(output, body, strlen(body));
free(body);
} }
else if (strcmp(method_name, "login") == 0) else if (strcmp(method_name, "login") == 0)
{ {
@ -2110,19 +2113,28 @@ client_on_read(struct bufferevent *bev, void *ctx)
} }
else if (strcmp(method_name, "keepalived") == 0) else if (strcmp(method_name, "keepalived") == 0)
{ {
char *body = stratum_new_status_body(client->json_id, "KEEPALIVED"); char body[STATUS_BODY_MAX];
stratum_get_status_body(body, client->json_id, "KEEPALIVED");
evbuffer_add(output, body, strlen(body)); evbuffer_add(output, body, strlen(body));
free(body);
} }
else else
{ {
char *body = stratum_new_error_body(client->json_id, unknown); unknown = true;
evbuffer_add(output, body, strlen(body));
free(body);
} }
json_object_put(message); json_object_put(message);
free(line); free(line);
if (unknown)
{
char body[ERROR_BODY_MAX];
stratum_get_error_body(body, client->json_id, unknown_method);
evbuffer_add(output, body, strlen(body));
log_info("Removing client. Unknown method called.");
evbuffer_drain(input, len);
client_clear(bev);
return;
}
} }
} }

View file

@ -84,23 +84,6 @@ bin_to_hex(const char *bin, size_t bin_size, char *hex)
} }
} }
void
reverse_hex(char *hex, size_t len)
{
assert(len % 2 == 0);
size_t start = 0;
size_t end = len-2;
char temp[2];
while (start < end)
{
memcpy(&temp[0], &hex[start], 2);
memcpy(&hex[start], &hex[end], 2);
memcpy(&hex[end], &temp[0], 2);
start += 2;
end -= 2;
}
}
void void
reverse_bin(char *bin, size_t len) reverse_bin(char *bin, size_t len)
{ {

View file

@ -36,7 +36,6 @@
int is_hex_string(const char *str); int is_hex_string(const char *str);
void hex_to_bin(const char *hex, char *bin, size_t bin_size); void hex_to_bin(const char *hex, char *bin, size_t bin_size);
void bin_to_hex(const char *bin, size_t bin_size, char *hex); void bin_to_hex(const char *bin, size_t bin_size, char *hex);
void reverse_hex(char *hex, size_t len);
void reverse_bin(char *bin, size_t len); void reverse_bin(char *bin, size_t len);
#endif #endif

View file

@ -15,6 +15,13 @@
table { table {
padding-bottom: 1em; padding-bottom: 1em;
} }
td {
vertical-align: top;
white-space: wrap;
}
td:last-child {
white-space: unset;
}
.wallet { .wallet {
display: none; display: none;
} }
@ -25,6 +32,7 @@
<table> <table>
<tr><td>Pool HR: </td><td id="pool_hashrate"></td></tr> <tr><td>Pool HR: </td><td id="pool_hashrate"></td></tr>
<tr><td>Network HR: </td><td id="network_hashrate"></td></tr> <tr><td>Network HR: </td><td id="network_hashrate"></td></tr>
<tr><td>Network height: </td><td id="network_height"></td></tr>
<tr><td>Blocks found: </td><td id="pool_blocks_found"></td></tr> <tr><td>Blocks found: </td><td id="pool_blocks_found"></td></tr>
<tr><td>Last block found: </td><td id="last_block_found"></td></tr> <tr><td>Last block found: </td><td id="last_block_found"></td></tr>
<tr><td>Payment threshold: </td><td id="payment_threshold"></td></tr> <tr><td>Payment threshold: </td><td id="payment_threshold"></td></tr>
@ -37,7 +45,7 @@
<td>Miner address: </td> <td>Miner address: </td>
<td> <td>
<form> <form>
<input type="text" id="wa" name="wa" size="8" /> <input type="text" id="wa" name="wa" />
<input type="submit" value="Submit" /> <input type="submit" value="Submit" />
</form> </form>
</td> </td>

View file

@ -70,6 +70,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection)
char json[JSON_MAX]; char json[JSON_MAX];
uint64_t ph = context->pool_stats->pool_hashrate; uint64_t ph = context->pool_stats->pool_hashrate;
uint64_t nh = context->pool_stats->network_hashrate; uint64_t nh = context->pool_stats->network_hashrate;
uint64_t height = context->pool_stats->network_height;
uint64_t lbf = context->pool_stats->last_block_found; uint64_t lbf = context->pool_stats->last_block_found;
uint32_t pbf = context->pool_stats->pool_blocks_found; uint32_t pbf = context->pool_stats->pool_blocks_found;
uint64_t mh = 0; uint64_t mh = 0;
@ -84,6 +85,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection)
snprintf(json, JSON_MAX, "{" snprintf(json, JSON_MAX, "{"
"\"pool_hashrate\":%"PRIu64"," "\"pool_hashrate\":%"PRIu64","
"\"network_hashrate\":%"PRIu64"," "\"network_hashrate\":%"PRIu64","
"\"network_height\":%"PRIu64","
"\"last_block_found\":%"PRIu64"," "\"last_block_found\":%"PRIu64","
"\"pool_blocks_found\":%d," "\"pool_blocks_found\":%d,"
"\"payment_threshold\":%.2f," "\"payment_threshold\":%.2f,"
@ -92,7 +94,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection)
"\"connected_miners\":%d," "\"connected_miners\":%d,"
"\"miner_hashrate\":%"PRIu64"," "\"miner_hashrate\":%"PRIu64","
"\"miner_balance\":%.8f" "\"miner_balance\":%.8f"
"}", ph, nh, lbf, pbf, "}", ph, nh, height, lbf, pbf,
context->payment_threshold, context->pool_fee, context->payment_threshold, context->pool_fee,
context->pool_port, context->pool_stats->connected_miners, context->pool_port, context->pool_stats->connected_miners,
mh, mb); mh, mb);

View file

@ -37,6 +37,7 @@ typedef struct pool_stats_t
{ {
uint64_t network_difficulty; uint64_t network_difficulty;
uint64_t network_hashrate; uint64_t network_hashrate;
uint64_t network_height;
uint32_t connected_miners; uint32_t connected_miners;
uint64_t pool_hashrate; uint64_t pool_hashrate;
uint32_t pool_blocks_found; uint32_t pool_blocks_found;

View file

@ -67,21 +67,6 @@ int get_hashing_blob(const char *input, const size_t in_size, char **output, siz
return 0; return 0;
} }
int construct_block_blob(const char *block_data, uint64_t nonce, char **blob)
{
struct block b = AUTO_VAL_INIT(b);
blobdata bd = block_data;
if (!parse_and_validate_block_from_blob(bd, b))
return -1;
b.nonce = nonce;
bd = "";
if (!block_to_blob(b, bd))
return -2;
*blob = (char*) malloc(bd.size());
memcpy(*blob, bd.data(), bd.length());
return 0;
}
int parse_address(const char *input, uint64_t *prefix) int parse_address(const char *input, uint64_t *prefix)
{ {
uint64_t tag; uint64_t tag;
@ -99,8 +84,3 @@ void get_hash(const char *input, const size_t in_size, char **output, int varian
crypto::cn_slow_hash(input, in_size, reinterpret_cast<crypto::hash&>(*output), variant, height); crypto::cn_slow_hash(input, in_size, reinterpret_cast<crypto::hash&>(*output), variant, height);
} }
bool check_hash(const char* hash, uint64_t difficulty)
{
return check_hash(reinterpret_cast<const crypto::hash&>(hash), difficulty);
}

View file

@ -38,10 +38,8 @@ extern "C" {
#endif #endif
int get_hashing_blob(const char *input, const size_t in_size, char **output, size_t *out_size); int get_hashing_blob(const char *input, const size_t in_size, char **output, size_t *out_size);
int construct_block_blob(const char *block_data, uint64_t nonce, char **blob);
int parse_address(const char *input, uint64_t *prefix); int parse_address(const char *input, uint64_t *prefix);
void get_hash(const char *input, const size_t in_size, char **output, int variant, uint64_t height); void get_hash(const char *input, const size_t in_size, char **output, int variant, uint64_t height);
bool check_hash(const char* hash, uint64_t difficulty);
#ifdef __cplusplus #ifdef __cplusplus
} }