diff --git a/src/pool.c b/src/pool.c
index d52e20f..ac701fa 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -1537,6 +1537,53 @@ rpc_on_block_template(const char* data, rpc_callback_t *callback)
json_object_put(root);
}
+static int
+startup_scan_round_shares()
+{
+ int rc;
+ char *err;
+ MDB_txn *txn;
+ MDB_cursor *cursor;
+
+ if ((rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0)
+ {
+ err = mdb_strerror(rc);
+ log_error("%s", err);
+ return rc;
+ }
+ if ((rc = mdb_cursor_open(txn, db_shares, &cursor)) != 0)
+ {
+ err = mdb_strerror(rc);
+ log_error("%s", err);
+ mdb_txn_abort(txn);
+ return rc;
+ }
+ MDB_cursor_op op = MDB_LAST;
+ while (1)
+ {
+ MDB_val key;
+ MDB_val val;
+ rc = mdb_cursor_get(cursor, &key, &val, op);
+ if (rc != 0 && rc != MDB_NOTFOUND)
+ {
+ err = mdb_strerror(rc);
+ log_error("%s", err);
+ break;
+ }
+ if (rc == MDB_NOTFOUND)
+ break;
+ op = MDB_PREV;
+ share_t *share = (share_t*)val.mv_data;
+ if (share->timestamp > pool_stats.last_block_found)
+ pool_stats.round_hashes += share->difficulty;
+ else
+ break;
+ }
+ mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
+ return 0;
+}
+
static int
startup_pauout(uint64_t height)
{
@@ -1668,6 +1715,7 @@ rpc_on_last_block_header(const char* data, rpc_callback_t *callback)
block_t *block = bstack_push(bsh, NULL);
response_to_block(block_header, block);
startup_pauout(block->height);
+ startup_scan_round_shares();
need_new_template = true;
}
@@ -1728,6 +1776,7 @@ rpc_on_block_submitted(const char* data, rpc_callback_t *callback)
pool_stats.pool_blocks_found++;
block_t *b = (block_t*)callback->data;
pool_stats.last_block_found = b->timestamp;
+ pool_stats.round_hashes = 0;
log_info("Block submitted at height: %"PRIu64, b->height);
int rc = store_block(b->height, b);
if (rc != 0)
@@ -2473,6 +2522,7 @@ client_on_submit(json_object *message, client_t *client)
share.difficulty = job->target;
strncpy(share.address, client->address, sizeof(share.address));
share.timestamp = now;
+ pool_stats.round_hashes += share.difficulty;
log_debug("Storing share with difficulty: %"PRIu64, share.difficulty);
int rc = store_share(share.height, &share);
if (rc != 0)
diff --git a/src/webui-embed.html b/src/webui-embed.html
index 633d5fe..8d8b808 100644
--- a/src/webui-embed.html
+++ b/src/webui-embed.html
@@ -52,6 +52,8 @@
Blocks found: | |
Last block found: | |
Last template: | |
+ Round HR: | |
+ Round hashes: | |
Payment threshold: | |
Pool fee: | |
Pool port: | |
@@ -93,16 +95,42 @@
}
}
- function format_hashrate(hr)
+ function format_hashes(h)
{
- if (hr < 1000)
- return parseInt(hr) + " H/s";
- else if (hr < 1000000)
- return parseFloat(hr/1000).toFixed(2) + " KH/s";
- else if (hr < 1000000000)
- return parseFloat(hr/1000000).toFixed(2) + " MH/s";
+ if (h < 1e-12)
+ return "0 H";
+ else if (h < 1e-9)
+ return parseFloat(h*1e+12).toFixed(2) + " pH";
+ else if (h < 1e-6)
+ return parseFloat(h*1e+9).toFixed(2) + " nH";
+ else if (h < 1e-3)
+ return parseFloat(h*1e+6).toFixed(2) + " μH";
+ else if (h < 1)
+ return parseFloat(h*1e+3).toFixed(2) + " mH";
+ else if (h < 1e+3)
+ return parseInt(h) + " H";
+ else if (h < 1e+6)
+ return parseFloat(h*1e-3).toFixed(2) + " KH";
+ else if (h < 1e+9)
+ return parseFloat(h*1e-6).toFixed(2) + " MH";
else
- return parseFloat(hr/1000000000).toFixed(2) + " GH/s";
+ return parseFloat(h*1e-9).toFixed(2) + " GH";
+ }
+
+ function format_hashrate(h)
+ {
+ return format_hashes(h) + "/s";
+ }
+
+ function format_round_hashrate(round_hashes, last_block_found)
+ {
+ var now = new Date().getTime() / 1000;
+ var diff = now - last_block_found;
+ if (last_block_found == 0)
+ return 0;
+ if (diff <= 0)
+ return 0;
+ return format_hashrate(round_hashes / diff)
}
var wf = document.querySelector(".address");
@@ -124,6 +152,12 @@
el.innerHTML = (stats[e]*100) + "%";
else if (e == "allow_self_select")
el.innerHTML = stats[e] == 1 ? "Yes" : "No";
+ else if (e == "round_hashes")
+ {
+ el.innerHTML = (stats[e]*100/stats["network_difficulty"]).toFixed(2) + "%"
+ el.innerHTML += " (" + format_hashes(stats[e]) + " / " + format_hashes(stats["network_difficulty"]) + ")";
+ document.querySelector("#round_hashrate").innerHTML = format_round_hashrate(stats["round_hashes"], stats["last_block_found"]);
+ }
else if (e == "pool_ssl_port")
{
el.closest("tr").style = "display: " +
diff --git a/src/webui.c b/src/webui.c
index c70fcd9..cb89e3c 100644
--- a/src/webui.c
+++ b/src/webui.c
@@ -68,10 +68,12 @@ send_json_stats(struct evhttp_request *req, void *arg)
struct evkeyvalq *hdrs_out = NULL;
uint64_t ph = context->pool_stats->pool_hashrate;
uint64_t nh = context->pool_stats->network_hashrate;
+ uint64_t nd = context->pool_stats->network_difficulty;
uint64_t height = context->pool_stats->network_height;
uint64_t ltf = context->pool_stats->last_template_fetched;
uint64_t lbf = context->pool_stats->last_block_found;
uint32_t pbf = context->pool_stats->pool_blocks_found;
+ uint64_t rh = context->pool_stats->round_hashes;
unsigned ss = context->allow_self_select;
uint64_t mh = 0;
double mb = 0.0;
@@ -92,7 +94,9 @@ send_json_stats(struct evhttp_request *req, void *arg)
evbuffer_add_printf(buf, "{"
"\"pool_hashrate\":%"PRIu64","
+ "\"round_hashes\":%"PRIu64","
"\"network_hashrate\":%"PRIu64","
+ "\"network_difficulty\":%"PRIu64","
"\"network_height\":%"PRIu64","
"\"last_template_fetched\":%"PRIu64","
"\"last_block_found\":%"PRIu64","
@@ -105,7 +109,7 @@ send_json_stats(struct evhttp_request *req, void *arg)
"\"connected_miners\":%d,"
"\"miner_hashrate\":%"PRIu64","
"\"miner_balance\":%.8f"
- "}", ph, nh, height, ltf, lbf, pbf,
+ "}", ph, rh, nh, nd, height, ltf, lbf, pbf,
context->payment_threshold, context->pool_fee,
context->pool_port, context->pool_ssl_port,
ss, context->pool_stats->connected_miners,
diff --git a/src/webui.h b/src/webui.h
index f76ff92..1ec1d7b 100644
--- a/src/webui.h
+++ b/src/webui.h
@@ -42,6 +42,7 @@ typedef struct pool_stats_t
uint64_t network_height;
uint32_t connected_miners;
uint64_t pool_hashrate;
+ uint64_t round_hashes;
uint32_t pool_blocks_found;
time_t last_block_found;
time_t last_template_fetched;