diff --git a/Makefile b/Makefile index 74da31c..59a4808 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ endif ifeq ($(OS),Darwin) LDPARAM = else -LDPARAM = -rdynamic -Wl,-warn-unresolved-symbols -fPIC -pie +LDPARAM = -Wl,-warn-unresolved-symbols -fPIC -pie endif ifeq ($(TYPE),debug) @@ -48,7 +48,7 @@ endif ifeq ($(TYPE), release) CCPARAM += -O3 -Wno-unused-variable ifneq ($(OS), Darwin) -LDPARAM = -rdynamic -Wl,--unresolved-symbols=ignore-in-object-files +LDPARAM = -Wl,--unresolved-symbols=ignore-in-object-files endif endif @@ -56,13 +56,13 @@ LDPARAM += $(LDFLAGS) LIBS := lmdb pthread microhttpd unbound 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 -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 PKG_LIBS := $(shell pkg-config \ - libevent \ + "libevent >= 2.1" \ json-c \ openssl \ libsodium \ @@ -74,7 +74,7 @@ DLIBS = INCPATH := $(DIRS) ${MONERO_INC} /opt/local/include /usr/local/include PKG_INC := $(shell pkg-config \ - libevent \ + "libevent >= 2.1" \ json-c \ openssl \ libsodium \ @@ -87,6 +87,7 @@ EXTRA_FILES = Makefile C++ = g++ CC = gcc +XXD := $(shell command -v xxd) STORE = build/$(TYPE) SOURCE := $(foreach DIR,$(DIRS),$(wildcard $(DIR)/*.cpp)) @@ -163,6 +164,12 @@ endif ifeq ($(origin MONERO_BUILD_ROOT), undefined) $(error You need to set an environment variable MONERO_BUILD_ROOT to your monero build root) endif +ifndef PKG_LIBS + $(error Missing dependencies) +endif +ifndef XXD + $(error Command xxd not found) +endif -include $(DFILES) -include $(CDFILES) diff --git a/src/pool.c b/src/pool.c index d5e0336..f1ffea1 100644 --- a/src/pool.c +++ b/src/pool.c @@ -68,7 +68,9 @@ #define MAX_LINE 4096 #define POOL_CLIENTS_GROW 1024 #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 BLOCK_HEADERS_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_send_job(); 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, - const block_template_t *block_template, const char *template_blob, - uint64_t target, bool response); -static char * stratum_new_job_body(int json_id, const char *client_id, const char *job_id, - const char *blob, uint64_t target, uint64_t height, bool response); -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 stratum_get_proxy_job_body(char *body, const client_t *client, + const char *block_hex, bool response); +static void stratum_get_job_body(char *body, const client_t *client, bool response); +static inline void stratum_get_error_body(char *body, int json_id, const char *error); +static inline void stratum_get_status_body(char *body, int json_id, const char *status); static void client_add(int fd, struct bufferevent *bev); static void client_find(struct bufferevent *bev, client_t **client); 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 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 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_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) 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)); c->cb = rpc_on_block_header_by_height; rpc_request(base, body, c); - free(body); } mdb_cursor_close(cursor); @@ -910,8 +910,7 @@ block_template_free(block_template_t *block_template) static void block_templates_free() { - size_t length = sizeof(last_block_headers)/sizeof(*last_block_headers); - for (size_t i=0; ijson_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]; target_to_hex(target, &target_hex[0]); - - const block_template_t *bt = block_template; + const block_template_t *bt = job->block_template; 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\"," "\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u," "\"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->reserved_offset + 8, target, target_hex); } 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\"," "\"difficulty\":%"PRIu64",\"height\":%"PRIu64",\"reserved_offset\":%u,\"client_nonce_offset\":%u," "\"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->reserved_offset + 8, target, target_hex); } - return body; } -static char * -stratum_new_job_body(int json_id, const char *client_id, const char *job_id, - const char *blob, uint64_t target, uint64_t height, bool response) +static void +stratum_get_job_body(char *body, const client_t *client, 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]; target_to_hex(target, &target_hex[0]); 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\":{" "\"blob\":\"%s\",\"job_id\":\"%.32s\",\"target\":\"%s\",\"height\":%"PRIu64"}," "\"status\":\"OK\"}}\n", json_id, client_id, blob, job_id, target_hex, height); } 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\"," "\"height\":%"PRIu64"}}\n", client_id, blob, job_id, target_hex, height); } - return body; } -static char * -stratum_new_error_body(int json_id, const char *error) +static inline void +stratum_get_error_body(char *body, int json_id, const char *error) { - char *body = calloc(512, sizeof(char)); - snprintf(body, 512, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":" + snprintf(body, ERROR_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":" "{\"code\":-1, \"message\":\"%s\"}}\n", json_id, error); - return body; } -static char * -stratum_new_status_body(int json_id, const char *status) +static inline void +stratum_get_status_body(char *body, int json_id, const char *status) { - char *body = calloc(256, sizeof(char)); - snprintf(body, 256, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\":{\"status\":\"%s\"}}\n", + snprintf(body, STATUS_BODY_MAX, "{\"id\":%d,\"jsonrpc\":\"2.0\",\"error\":null,\"result\":{\"status\":\"%s\"}}\n", json_id, status); - return body; } static void @@ -1128,21 +1126,20 @@ response_to_block(json_object *block_header, block_t *block) block->status |= BLOCK_ORPHANED; } -static char * -rpc_new_request_body(const char* method, char* fmt, ...) +static void +rpc_get_request_body(char *body, const char* method, char* fmt, ...) { - char *result = calloc(RPC_BODY_MAX, sizeof(char)); - char *pr = &result[0]; + char *pb = body; - snprintf(pr, RPC_BODY_MAX, "%s%s%s", "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"", method, "\""); - pr += strlen(pr); + snprintf(pb, RPC_BODY_MAX, "%s%s%s", "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"", method, "\""); + pb += strlen(pb); if (fmt && *fmt) { char *s; uint64_t d; - snprintf(pr, RPC_BODY_MAX - strlen(result), "%s", ",\"params\":{"); - pr += strlen(pr); + snprintf(pb, RPC_BODY_MAX - strlen(body), "%s", ",\"params\":{"); + pb += strlen(pb); va_list args; va_start(args, fmt); uint8_t count = 0; @@ -1152,27 +1149,26 @@ rpc_new_request_body(const char* method, char* fmt, ...) { case 's': s = va_arg(args, char *); - snprintf(pr, RPC_BODY_MAX - strlen(result), "\"%s\"", s); - pr += strlen(pr); + snprintf(pb, RPC_BODY_MAX - strlen(body), "\"%s\"", s); + pb += strlen(pb); break; case 'd': d = va_arg(args, uint64_t); - snprintf(pr, RPC_BODY_MAX - strlen(result), "%"PRIu64, d); - pr += strlen(pr); + snprintf(pb, RPC_BODY_MAX - strlen(body), "%"PRIu64, d); + pb += strlen(pb); break; } char append = ':'; if (count++ % 2 != 0) append = ','; - *pr++ = append; + *pb++ = append; } va_end(args); - *--pr = '}'; - pr++; + *--pb = '}'; + pb++; } - *pr = '}'; - log_trace("Payload: %s", result); - return result; + *pb = '}'; + log_trace("Payload: %s", body); } static void @@ -1184,22 +1180,23 @@ rpc_on_response(struct evhttp_request *req, void *arg) if (!req) { log_error("Request failure. Aborting."); - return; + goto cleanup; } int rc = evhttp_request_get_response_code(req); if (rc < 200 || rc >= 300) { 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); size_t len = evbuffer_get_length(input); - char data[len+1]; + char *data = (char*) alloca(len+1); evbuffer_remove(input, data, len); data[len] = '\0'; - callback->cb(&data[0], callback); + callback->cb(data, callback); +cleanup: if (callback->data) free(callback->data); free(callback); @@ -1214,6 +1211,7 @@ rpc_request(struct event_base *base, const char *body, rpc_callback_t *callback) struct evbuffer *output; 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); req = evhttp_request_new(rpc_on_response, callback); 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; 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); req = evhttp_request_new(rpc_on_response, callback); 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); size_t headers_len = json_object_array_length(headers); + assert(headers_len == BLOCK_HEADERS_RANGE); for (int i=0; idifficulty; pool_stats.network_hashrate = last_block_headers[0]->difficulty / BLOCK_TIME; + pool_stats.network_height = last_block_headers[0]->height; update_pool_hr(); if (need_new_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)); c1->cb = rpc_on_block_template; rpc_request(base, body, c1); - free(body); - uint32_t end = block->height - 60; - uint32_t start = end - BLOCK_HEADERS_RANGE + 1; - body = rpc_new_request_body("get_block_headers_range", "sdsd", "start_height", start, "end_height", end); + uint64_t end = block->height - 60; + uint64_t start = end - BLOCK_HEADERS_RANGE + 1; + 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)); c2->cb = rpc_on_block_headers_range; rpc_request(base, body, c2); - free(body); } json_object_put(root); @@ -1591,11 +1592,11 @@ static void timer_on_120s(int fd, short kind, void *ctx) { 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)); callback->cb = rpc_on_last_block_header; rpc_request(base, body, callback); - free(body); struct timeval timeout = { .tv_sec = 120, .tv_usec = 0 }; evtimer_add(timer_120s, &timeout); } @@ -1747,23 +1748,21 @@ client_send_job(client_t *client, bool response) job->target = target; log_debug("Client %.32s target now %"PRIu64, client->client_id, target); - char *body; + char body[JOB_BODY_MAX]; if (!client->is_proxy) { - body = stratum_new_job_body(client->json_id, client->client_id, job_id, - job->blob, target, bt->height, response); + stratum_get_job_body(body, client, response); } else { - char *template_hex = calloc(bin_size+1, sizeof(char)); - bin_to_hex(block, bin_size, template_hex); - body = stratum_new_proxy_job_body(client->json_id, client->client_id, job_id, - bt, template_hex, target, response); + char *block_hex = calloc(bin_size+1, sizeof(char)); + bin_to_hex(block, bin_size, block_hex); + stratum_get_proxy_job_body(body, client, block_hex, response); + free(block_hex); } log_trace("Client job: %s", body); struct evbuffer *output = bufferevent_get_output(client->bev); evbuffer_add(output, body, strlen(body)); - free(body); free(block); free(hashing_blob); } @@ -1792,10 +1791,10 @@ static void send_validation_error(const client_t *client, const char *message) { 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)); log_debug("Validation error: %s", message); - free(body); } static void @@ -1930,10 +1929,10 @@ client_on_submit(json_object *message, client_t *client) { 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)); log_debug("Duplicate share"); - free(body); free(block); return; } @@ -1952,10 +1951,10 @@ client_on_submit(json_object *message, client_t *client) char *hashing_blob = NULL; 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)); log_debug("Invalid block"); - free(body); free(block); return; } @@ -1970,11 +1969,11 @@ client_on_submit(json_object *message, client_t *client) 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)); log_debug("Invalid share"); /* TODO: record and ban if too many */ - free(body); free(block); free(hashing_blob); return; @@ -2005,9 +2004,10 @@ client_on_submit(json_object *message, client_t *client) log_info("+++ MINED A BLOCK +++"); char *block_hex = calloc((bin_size << 1)+1, sizeof(char)); 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, - "{\"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)); callback->cb = rpc_on_block_submitted; @@ -2022,16 +2022,15 @@ client_on_submit(json_object *message, client_t *client) b->timestamp = now; rpc_request(base, body, callback); - free(body); free(block_hex); } else if (BN_cmp(hd, jd) < 0) { 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)); evbuffer_add(output, body, strlen(body)); - free(body); } else can_store = true; @@ -2053,15 +2052,16 @@ client_on_submit(json_object *message, client_t *client) int rc = store_share(share.height, &share); if (rc != 0) 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)); - free(body); } } static void client_on_read(struct bufferevent *bev, void *ctx) { + const char unknown_method[] = "Unknown method"; struct evbuffer *input, *output; char *line; size_t n; @@ -2074,10 +2074,14 @@ client_on_read(struct bufferevent *bev, void *ctx) input = bufferevent_get_input(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"; evbuffer_add(output, too_long, strlen(too_long)); + log_info("Removing client. Message too long."); + evbuffer_drain(input, len); + client_clear(bev); 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(id, message, json_type_int); const char *method_name = json_object_get_string(method); - const char unknown[] = "Unknown method"; client->json_id = json_object_get_int(id); + bool unknown = false; + if (method_name == NULL) { - char *body = stratum_new_error_body(client->json_id, unknown); - evbuffer_add(output, body, strlen(body)); - free(body); + unknown = true; } 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) { - 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)); - free(body); } else { - char *body = stratum_new_error_body(client->json_id, unknown); - evbuffer_add(output, body, strlen(body)); - free(body); + unknown = true; } json_object_put(message); 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; + } } } diff --git a/src/util.c b/src/util.c index addb081..8dd6b32 100644 --- a/src/util.c +++ b/src/util.c @@ -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 reverse_bin(char *bin, size_t len) { diff --git a/src/util.h b/src/util.h index a23d97e..858e52a 100644 --- a/src/util.h +++ b/src/util.h @@ -36,7 +36,6 @@ int is_hex_string(const char *str); 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 reverse_hex(char *hex, size_t len); void reverse_bin(char *bin, size_t len); #endif diff --git a/src/webui-embed.html b/src/webui-embed.html index c7f4475..b3da59d 100644 --- a/src/webui-embed.html +++ b/src/webui-embed.html @@ -15,6 +15,13 @@ table { padding-bottom: 1em; } + td { + vertical-align: top; + white-space: wrap; + } + td:last-child { + white-space: unset; + } .wallet { display: none; } @@ -25,6 +32,7 @@ + @@ -37,7 +45,7 @@ diff --git a/src/webui.c b/src/webui.c index 598a403..87deefa 100644 --- a/src/webui.c +++ b/src/webui.c @@ -70,6 +70,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection) char json[JSON_MAX]; uint64_t ph = context->pool_stats->pool_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; uint32_t pbf = context->pool_stats->pool_blocks_found; uint64_t mh = 0; @@ -84,6 +85,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection) snprintf(json, JSON_MAX, "{" "\"pool_hashrate\":%"PRIu64"," "\"network_hashrate\":%"PRIu64"," + "\"network_height\":%"PRIu64"," "\"last_block_found\":%"PRIu64"," "\"pool_blocks_found\":%d," "\"payment_threshold\":%.2f," @@ -92,7 +94,7 @@ send_json_stats (void *cls, struct MHD_Connection *connection) "\"connected_miners\":%d," "\"miner_hashrate\":%"PRIu64"," "\"miner_balance\":%.8f" - "}", ph, nh, lbf, pbf, + "}", ph, nh, height, lbf, pbf, context->payment_threshold, context->pool_fee, context->pool_port, context->pool_stats->connected_miners, mh, mb); diff --git a/src/webui.h b/src/webui.h index 8065759..3ca4dee 100644 --- a/src/webui.h +++ b/src/webui.h @@ -37,6 +37,7 @@ typedef struct pool_stats_t { uint64_t network_difficulty; uint64_t network_hashrate; + uint64_t network_height; uint32_t connected_miners; uint64_t pool_hashrate; uint32_t pool_blocks_found; diff --git a/src/xmr.cpp b/src/xmr.cpp index 36328f3..8499600 100644 --- a/src/xmr.cpp +++ b/src/xmr.cpp @@ -67,21 +67,6 @@ int get_hashing_blob(const char *input, const size_t in_size, char **output, siz 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) { 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(*output), variant, height); } -bool check_hash(const char* hash, uint64_t difficulty) -{ - return check_hash(reinterpret_cast(hash), difficulty); -} - diff --git a/src/xmr.h b/src/xmr.h index 8e1c250..79d04d6 100644 --- a/src/xmr.h +++ b/src/xmr.h @@ -38,10 +38,8 @@ extern "C" { #endif 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); 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 }
Pool HR:
Network HR:
Network height:
Blocks found:
Last block found:
Payment threshold:
Miner address:
- +