|
|
@ -28,10 +28,19 @@ |
|
|
|
#include "uthash.h" |
|
|
|
#include "uthash.h" |
|
|
|
#include "utlist.h" |
|
|
|
#include "utlist.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MIN1 60 |
|
|
|
|
|
|
|
#define MIN5 300 |
|
|
|
|
|
|
|
#define MIN15 900 |
|
|
|
|
|
|
|
#define HOUR 3600 |
|
|
|
|
|
|
|
#define HOUR6 21600 |
|
|
|
|
|
|
|
#define DAY 86400 |
|
|
|
|
|
|
|
#define WEEK 604800 |
|
|
|
|
|
|
|
|
|
|
|
/* Consistent across all pool instances */ |
|
|
|
/* Consistent across all pool instances */ |
|
|
|
static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; |
|
|
|
static const char *workpadding = "000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000"; |
|
|
|
static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff"; |
|
|
|
static const char *scriptsig_header = "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff"; |
|
|
|
static uchar scriptsig_header_bin[41]; |
|
|
|
static uchar scriptsig_header_bin[41]; |
|
|
|
|
|
|
|
static const double nonces = 4294967296; |
|
|
|
|
|
|
|
|
|
|
|
/* Add unaccounted shares when they arrive, remove them with each update of
|
|
|
|
/* Add unaccounted shares when they arrive, remove them with each update of
|
|
|
|
* rolling stats. */ |
|
|
|
* rolling stats. */ |
|
|
@ -173,12 +182,14 @@ struct user_instance { |
|
|
|
|
|
|
|
|
|
|
|
double best_diff; /* Best share found by this user */ |
|
|
|
double best_diff; /* Best share found by this user */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64_t shares; |
|
|
|
double dsps1; /* Diff shares per second, 1 minute rolling average */ |
|
|
|
double dsps1; /* Diff shares per second, 1 minute rolling average */ |
|
|
|
double dsps5; /* ... 5 minute ... */ |
|
|
|
double dsps5; /* ... 5 minute ... */ |
|
|
|
double dsps60;/* etc */ |
|
|
|
double dsps60;/* etc */ |
|
|
|
double dsps1440; |
|
|
|
double dsps1440; |
|
|
|
double dsps10080; |
|
|
|
double dsps10080; |
|
|
|
tv_t last_share; |
|
|
|
tv_t last_share; |
|
|
|
|
|
|
|
tv_t last_decay; |
|
|
|
tv_t last_update; |
|
|
|
tv_t last_update; |
|
|
|
|
|
|
|
|
|
|
|
bool authorised; /* Has this username ever been authorised? */ |
|
|
|
bool authorised; /* Has this username ever been authorised? */ |
|
|
@ -196,11 +207,14 @@ struct worker_instance { |
|
|
|
worker_instance_t *next; |
|
|
|
worker_instance_t *next; |
|
|
|
worker_instance_t *prev; |
|
|
|
worker_instance_t *prev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int64_t shares; |
|
|
|
double dsps1; |
|
|
|
double dsps1; |
|
|
|
double dsps5; |
|
|
|
double dsps5; |
|
|
|
double dsps60; |
|
|
|
double dsps60; |
|
|
|
double dsps1440; |
|
|
|
double dsps1440; |
|
|
|
|
|
|
|
double dsps10080; |
|
|
|
tv_t last_share; |
|
|
|
tv_t last_share; |
|
|
|
|
|
|
|
tv_t last_decay; |
|
|
|
tv_t last_update; |
|
|
|
tv_t last_update; |
|
|
|
time_t start_time; |
|
|
|
time_t start_time; |
|
|
|
|
|
|
|
|
|
|
@ -241,6 +255,7 @@ struct stratum_instance { |
|
|
|
int ssdc; /* Shares since diff change */ |
|
|
|
int ssdc; /* Shares since diff change */ |
|
|
|
tv_t first_share; |
|
|
|
tv_t first_share; |
|
|
|
tv_t last_share; |
|
|
|
tv_t last_share; |
|
|
|
|
|
|
|
tv_t last_decay; |
|
|
|
time_t first_invalid; /* Time of first invalid in run of non stale rejects */ |
|
|
|
time_t first_invalid; /* Time of first invalid in run of non stale rejects */ |
|
|
|
time_t start_time; |
|
|
|
time_t start_time; |
|
|
|
|
|
|
|
|
|
|
@ -679,10 +694,15 @@ static void _ckdbq_add(ckpool_t *ckp, const int idtype, json_t *val, const char |
|
|
|
|
|
|
|
|
|
|
|
now_t = time(NULL); |
|
|
|
now_t = time(NULL); |
|
|
|
if (now_t != time_counter) { |
|
|
|
if (now_t != time_counter) { |
|
|
|
|
|
|
|
pool_stats_t *stats = &sdata->stats; |
|
|
|
|
|
|
|
char hashrate[16]; |
|
|
|
|
|
|
|
|
|
|
|
/* Rate limit to 1 update per second */ |
|
|
|
/* Rate limit to 1 update per second */ |
|
|
|
time_counter = now_t; |
|
|
|
time_counter = now_t; |
|
|
|
|
|
|
|
suffix_string(stats->dsps1 * nonces, hashrate, 16, 3); |
|
|
|
ch = status_chars[(counter++) & 0x3]; |
|
|
|
ch = status_chars[(counter++) & 0x3]; |
|
|
|
fprintf(stdout, "%c\r", ch); |
|
|
|
fprintf(stdout, "\33[2K\r%c %sH/s %.1f SPS %d users %d workers", |
|
|
|
|
|
|
|
ch, hashrate, stats->sps1, stats->users, stats->workers); |
|
|
|
fflush(stdout); |
|
|
|
fflush(stdout); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1560,15 +1580,92 @@ static void reset_bestshares(sdata_t *sdata) |
|
|
|
ck_runlock(&sdata->instance_lock); |
|
|
|
ck_runlock(&sdata->instance_lock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static user_instance_t *get_user(sdata_t *sdata, const char *username); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static user_instance_t *user_by_workername(sdata_t *sdata, const char *workername) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *username = strdupa(workername), *ignore; |
|
|
|
|
|
|
|
user_instance_t *user; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ignore = username; |
|
|
|
|
|
|
|
strsep(&ignore, "._"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Find the user first */ |
|
|
|
|
|
|
|
user = get_user(sdata, username); |
|
|
|
|
|
|
|
return user; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static worker_instance_t *get_worker(sdata_t *sdata, user_instance_t *user, const char *workername); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static json_t *worker_stats(const worker_instance_t *worker) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char suffix1[16], suffix5[16], suffix60[16], suffix1440[16], suffix10080[16]; |
|
|
|
|
|
|
|
json_t *val; |
|
|
|
|
|
|
|
double ghs; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps1 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix1, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps5 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix5, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps60 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix60, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps1440 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps10080 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix10080, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss}", |
|
|
|
|
|
|
|
"hashrate1m", suffix1, |
|
|
|
|
|
|
|
"hashrate5m", suffix5, |
|
|
|
|
|
|
|
"hashrate1hr", suffix60, |
|
|
|
|
|
|
|
"hashrate1d", suffix1440, |
|
|
|
|
|
|
|
"hashrate7d", suffix10080); |
|
|
|
|
|
|
|
return val; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static json_t *user_stats(const user_instance_t *user) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char suffix1[16], suffix5[16], suffix60[16], suffix1440[16], suffix10080[16]; |
|
|
|
|
|
|
|
json_t *val; |
|
|
|
|
|
|
|
double ghs; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = user->dsps1 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix1, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = user->dsps5 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix5, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = user->dsps60 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix60, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = user->dsps1440 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = user->dsps10080 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix10080, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss}", |
|
|
|
|
|
|
|
"hashrate1m", suffix1, |
|
|
|
|
|
|
|
"hashrate5m", suffix5, |
|
|
|
|
|
|
|
"hashrate1hr", suffix60, |
|
|
|
|
|
|
|
"hashrate1d", suffix1440, |
|
|
|
|
|
|
|
"hashrate7d", suffix10080); |
|
|
|
|
|
|
|
return val; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void block_solve(ckpool_t *ckp, const char *blockhash) |
|
|
|
static void block_solve(ckpool_t *ckp, const char *blockhash) |
|
|
|
{ |
|
|
|
{ |
|
|
|
ckmsg_t *block, *tmp, *found = NULL; |
|
|
|
ckmsg_t *block, *tmp, *found = NULL; |
|
|
|
|
|
|
|
char *msg, *workername = NULL; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
char cdfield[64]; |
|
|
|
char cdfield[64]; |
|
|
|
int height = 0; |
|
|
|
int height = 0; |
|
|
|
ts_t ts_now; |
|
|
|
ts_t ts_now; |
|
|
|
json_t *val; |
|
|
|
json_t *val; |
|
|
|
char *msg; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
update_base(ckp, GEN_PRIORITY); |
|
|
|
update_base(ckp, GEN_PRIORITY); |
|
|
|
|
|
|
|
|
|
|
@ -1587,6 +1684,7 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) |
|
|
|
} |
|
|
|
} |
|
|
|
if (!strcmp(solvehash, blockhash)) { |
|
|
|
if (!strcmp(solvehash, blockhash)) { |
|
|
|
dealloc(solvehash); |
|
|
|
dealloc(solvehash); |
|
|
|
|
|
|
|
json_get_string(&workername, val, "workername"); |
|
|
|
found = block; |
|
|
|
found = block; |
|
|
|
DL_DELETE(sdata->block_solves, block); |
|
|
|
DL_DELETE(sdata->block_solves, block); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -1608,11 +1706,40 @@ static void block_solve(ckpool_t *ckp, const char *blockhash) |
|
|
|
ckdbq_add(ckp, ID_BLOCK, val); |
|
|
|
ckdbq_add(ckp, ID_BLOCK, val); |
|
|
|
free(found); |
|
|
|
free(found); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(!workername)) { |
|
|
|
|
|
|
|
/* This should be impossible! */ |
|
|
|
ASPRINTF(&msg, "Block %d solved by %s!", height, ckp->name); |
|
|
|
ASPRINTF(&msg, "Block %d solved by %s!", height, ckp->name); |
|
|
|
|
|
|
|
LOGWARNING("Solved and confirmed block %d", height); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
json_t *user_val, *worker_val; |
|
|
|
|
|
|
|
worker_instance_t *worker; |
|
|
|
|
|
|
|
user_instance_t *user; |
|
|
|
|
|
|
|
char *s; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ASPRINTF(&msg, "Block %d solved by %s @ %s!", height, workername, ckp->name); |
|
|
|
|
|
|
|
LOGWARNING("Solved and confirmed block %d by %s", height, workername); |
|
|
|
|
|
|
|
user = user_by_workername(sdata, workername); |
|
|
|
|
|
|
|
worker = get_worker(sdata, user, workername); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ck_rlock(&sdata->instance_lock); |
|
|
|
|
|
|
|
user_val = user_stats(user); |
|
|
|
|
|
|
|
worker_val = worker_stats(worker); |
|
|
|
|
|
|
|
ck_runlock(&sdata->instance_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s = json_dumps(user_val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); |
|
|
|
|
|
|
|
json_decref(user_val); |
|
|
|
|
|
|
|
LOGWARNING("User %s:%s", user->username, s); |
|
|
|
|
|
|
|
dealloc(s); |
|
|
|
|
|
|
|
s = json_dumps(worker_val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); |
|
|
|
|
|
|
|
json_decref(worker_val); |
|
|
|
|
|
|
|
LOGWARNING("Worker %s:%s", workername, s); |
|
|
|
|
|
|
|
dealloc(s); |
|
|
|
|
|
|
|
} |
|
|
|
stratum_broadcast_message(sdata, msg); |
|
|
|
stratum_broadcast_message(sdata, msg); |
|
|
|
free(msg); |
|
|
|
free(msg); |
|
|
|
|
|
|
|
|
|
|
|
LOGWARNING("Solved and confirmed block %d", height); |
|
|
|
free(workername); |
|
|
|
|
|
|
|
|
|
|
|
reset_bestshares(sdata); |
|
|
|
reset_bestshares(sdata); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2076,8 +2203,6 @@ static bool test_address(ckpool_t *ckp, const char *address) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static const double nonces = 4294967296; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static double dsps_from_key(json_t *val, const char *key) |
|
|
|
static double dsps_from_key(json_t *val, const char *key) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *string, *endptr; |
|
|
|
char *string, *endptr; |
|
|
@ -2109,6 +2234,52 @@ static double dsps_from_key(json_t *val, const char *key) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Sanity check to prevent clock adjustments backwards from screwing up stats */ |
|
|
|
|
|
|
|
static double sane_tdiff(tv_t *end, tv_t *start) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double tdiff = tvdiff(end, start); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(tdiff < 0.001)) |
|
|
|
|
|
|
|
tdiff = 0.001; |
|
|
|
|
|
|
|
return tdiff; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void decay_client(stratum_instance_t *client, double diff, tv_t *now_t) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double tdiff = sane_tdiff(now_t, &client->last_decay); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decay_time(&client->dsps1, diff, tdiff, MIN1); |
|
|
|
|
|
|
|
decay_time(&client->dsps5, diff, tdiff, MIN5); |
|
|
|
|
|
|
|
decay_time(&client->dsps60, diff, tdiff, HOUR); |
|
|
|
|
|
|
|
decay_time(&client->dsps1440, diff, tdiff, DAY); |
|
|
|
|
|
|
|
decay_time(&client->dsps10080, diff, tdiff, WEEK); |
|
|
|
|
|
|
|
copy_tv(&client->last_decay, now_t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void decay_worker(worker_instance_t *worker, double diff, tv_t *now_t) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double tdiff = sane_tdiff(now_t, &worker->last_decay); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decay_time(&worker->dsps1, diff, tdiff, MIN1); |
|
|
|
|
|
|
|
decay_time(&worker->dsps5, diff, tdiff, MIN5); |
|
|
|
|
|
|
|
decay_time(&worker->dsps60, diff, tdiff, HOUR); |
|
|
|
|
|
|
|
decay_time(&worker->dsps1440, diff, tdiff, DAY); |
|
|
|
|
|
|
|
decay_time(&worker->dsps10080, diff, tdiff, WEEK); |
|
|
|
|
|
|
|
copy_tv(&worker->last_decay, now_t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void decay_user(user_instance_t *user, double diff, tv_t *now_t) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double tdiff = sane_tdiff(now_t, &user->last_decay); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
decay_time(&user->dsps1, diff, tdiff, MIN1); |
|
|
|
|
|
|
|
decay_time(&user->dsps5, diff, tdiff, MIN5); |
|
|
|
|
|
|
|
decay_time(&user->dsps60, diff, tdiff, HOUR); |
|
|
|
|
|
|
|
decay_time(&user->dsps1440, diff, tdiff, DAY); |
|
|
|
|
|
|
|
decay_time(&user->dsps10080, diff, tdiff, WEEK); |
|
|
|
|
|
|
|
copy_tv(&user->last_decay, now_t); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Enter holding a reference count */ |
|
|
|
/* Enter holding a reference count */ |
|
|
|
static void read_userstats(ckpool_t *ckp, user_instance_t *user) |
|
|
|
static void read_userstats(ckpool_t *ckp, user_instance_t *user) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -2139,12 +2310,14 @@ static void read_userstats(ckpool_t *ckp, user_instance_t *user) |
|
|
|
|
|
|
|
|
|
|
|
tv_time(&now); |
|
|
|
tv_time(&now); |
|
|
|
copy_tv(&user->last_share, &now); |
|
|
|
copy_tv(&user->last_share, &now); |
|
|
|
|
|
|
|
copy_tv(&user->last_decay, &now); |
|
|
|
user->dsps1 = dsps_from_key(val, "hashrate1m"); |
|
|
|
user->dsps1 = dsps_from_key(val, "hashrate1m"); |
|
|
|
user->dsps5 = dsps_from_key(val, "hashrate5m"); |
|
|
|
user->dsps5 = dsps_from_key(val, "hashrate5m"); |
|
|
|
user->dsps60 = dsps_from_key(val, "hashrate1hr"); |
|
|
|
user->dsps60 = dsps_from_key(val, "hashrate1hr"); |
|
|
|
user->dsps1440 = dsps_from_key(val, "hashrate1d"); |
|
|
|
user->dsps1440 = dsps_from_key(val, "hashrate1d"); |
|
|
|
user->dsps10080 = dsps_from_key(val, "hashrate7d"); |
|
|
|
user->dsps10080 = dsps_from_key(val, "hashrate7d"); |
|
|
|
json_get_int64(&user->last_update.tv_sec, val, "lastupdate"); |
|
|
|
json_get_int64(&user->last_update.tv_sec, val, "lastupdate"); |
|
|
|
|
|
|
|
json_get_int64(&user->shares, val, "shares"); |
|
|
|
json_get_double(&user->best_diff, val, "bestshare"); |
|
|
|
json_get_double(&user->best_diff, val, "bestshare"); |
|
|
|
LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", user->username, |
|
|
|
LOGINFO("Successfully read user %s stats %f %f %f %f %f %f", user->username, |
|
|
|
user->dsps1, user->dsps5, user->dsps60, user->dsps1440, |
|
|
|
user->dsps1, user->dsps5, user->dsps60, user->dsps1440, |
|
|
@ -2155,11 +2328,7 @@ static void read_userstats(ckpool_t *ckp, user_instance_t *user) |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
LOGINFO("Old user stats indicate not logged for %d seconds, decaying stats", |
|
|
|
LOGINFO("Old user stats indicate not logged for %d seconds, decaying stats", |
|
|
|
tvsec_diff); |
|
|
|
tvsec_diff); |
|
|
|
decay_time(&user->dsps1, 0, tvsec_diff, 60); |
|
|
|
decay_user(user, 0, &now); |
|
|
|
decay_time(&user->dsps5, 0, tvsec_diff, 300); |
|
|
|
|
|
|
|
decay_time(&user->dsps60, 0, tvsec_diff, 3600); |
|
|
|
|
|
|
|
decay_time(&user->dsps1440, 0, tvsec_diff, 86400); |
|
|
|
|
|
|
|
decay_time(&user->dsps10080, 0, tvsec_diff, 604800); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2193,12 +2362,15 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker) |
|
|
|
|
|
|
|
|
|
|
|
tv_time(&now); |
|
|
|
tv_time(&now); |
|
|
|
copy_tv(&worker->last_share, &now); |
|
|
|
copy_tv(&worker->last_share, &now); |
|
|
|
|
|
|
|
copy_tv(&worker->last_decay, &now); |
|
|
|
worker->dsps1 = dsps_from_key(val, "hashrate1m"); |
|
|
|
worker->dsps1 = dsps_from_key(val, "hashrate1m"); |
|
|
|
worker->dsps5 = dsps_from_key(val, "hashrate5m"); |
|
|
|
worker->dsps5 = dsps_from_key(val, "hashrate5m"); |
|
|
|
worker->dsps60 = dsps_from_key(val, "hashrate1d"); |
|
|
|
worker->dsps60 = dsps_from_key(val, "hashrate1d"); |
|
|
|
worker->dsps1440 = dsps_from_key(val, "hashrate1d"); |
|
|
|
worker->dsps1440 = dsps_from_key(val, "hashrate1d"); |
|
|
|
|
|
|
|
worker->dsps10080 = dsps_from_key(val, "hashrate7d"); |
|
|
|
json_get_double(&worker->best_diff, val, "bestshare"); |
|
|
|
json_get_double(&worker->best_diff, val, "bestshare"); |
|
|
|
json_get_int64(&worker->last_update.tv_sec, val, "lastupdate"); |
|
|
|
json_get_int64(&worker->last_update.tv_sec, val, "lastupdate"); |
|
|
|
|
|
|
|
json_get_int64(&worker->shares, val, "shares"); |
|
|
|
LOGINFO("Successfully read worker %s stats %f %f %f %f %f", worker->workername, |
|
|
|
LOGINFO("Successfully read worker %s stats %f %f %f %f %f", worker->workername, |
|
|
|
worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440, worker->best_diff); |
|
|
|
worker->dsps1, worker->dsps5, worker->dsps60, worker->dsps1440, worker->best_diff); |
|
|
|
json_decref(val); |
|
|
|
json_decref(val); |
|
|
@ -2207,10 +2379,7 @@ static void read_workerstats(ckpool_t *ckp, worker_instance_t *worker) |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
LOGINFO("Old worker stats indicate not logged for %d seconds, decaying stats", |
|
|
|
LOGINFO("Old worker stats indicate not logged for %d seconds, decaying stats", |
|
|
|
tvsec_diff); |
|
|
|
tvsec_diff); |
|
|
|
decay_time(&worker->dsps1, 0, tvsec_diff, 60); |
|
|
|
decay_worker(worker, 0, &now); |
|
|
|
decay_time(&worker->dsps5, 0, tvsec_diff, 300); |
|
|
|
|
|
|
|
decay_time(&worker->dsps60, 0, tvsec_diff, 3600); |
|
|
|
|
|
|
|
decay_time(&worker->dsps1440, 0, tvsec_diff, 86400); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2636,16 +2805,6 @@ static double time_bias(const double tdiff, const double period) |
|
|
|
return 1.0 - 1.0 / exp(dexp); |
|
|
|
return 1.0 - 1.0 / exp(dexp); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Sanity check to prevent clock adjustments backwards from screwing up stats */ |
|
|
|
|
|
|
|
static double sane_tdiff(tv_t *end, tv_t *start) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
double tdiff = tvdiff(end, start); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(tdiff < 0.001)) |
|
|
|
|
|
|
|
tdiff = 0.001; |
|
|
|
|
|
|
|
return tdiff; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Needs to be entered with client holding a ref count. */ |
|
|
|
/* Needs to be entered with client holding a ref count. */ |
|
|
|
static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff, const bool valid, |
|
|
|
static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff, const bool valid, |
|
|
|
const bool submit) |
|
|
|
const bool submit) |
|
|
@ -2666,7 +2825,10 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff |
|
|
|
mutex_unlock(&sdata->stats_lock); |
|
|
|
mutex_unlock(&sdata->stats_lock); |
|
|
|
|
|
|
|
|
|
|
|
/* Count only accepted and stale rejects in diff calculation. */ |
|
|
|
/* Count only accepted and stale rejects in diff calculation. */ |
|
|
|
if (!valid && !submit) |
|
|
|
if (valid) { |
|
|
|
|
|
|
|
worker->shares += diff; |
|
|
|
|
|
|
|
user->shares += diff; |
|
|
|
|
|
|
|
} else if (!submit) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
tv_time(&now_t); |
|
|
|
tv_time(&now_t); |
|
|
@ -2684,28 +2846,14 @@ static void add_submit(ckpool_t *ckp, stratum_instance_t *client, const int diff |
|
|
|
copy_tv(&client->ldc, &now_t); |
|
|
|
copy_tv(&client->ldc, &now_t); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tdiff = sane_tdiff(&now_t, &client->last_share); |
|
|
|
decay_client(client, diff, &now_t); |
|
|
|
decay_time(&client->dsps1, diff, tdiff, 60); |
|
|
|
|
|
|
|
decay_time(&client->dsps5, diff, tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&client->dsps60, diff, tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&client->dsps1440, diff, tdiff, 86400); |
|
|
|
|
|
|
|
decay_time(&client->dsps10080, diff, tdiff, 604800); |
|
|
|
|
|
|
|
copy_tv(&client->last_share, &now_t); |
|
|
|
copy_tv(&client->last_share, &now_t); |
|
|
|
|
|
|
|
|
|
|
|
tdiff = sane_tdiff(&now_t, &worker->last_share); |
|
|
|
decay_worker(worker, diff, &now_t); |
|
|
|
decay_time(&worker->dsps1, diff, tdiff, 60); |
|
|
|
|
|
|
|
decay_time(&worker->dsps5, diff, tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&worker->dsps60, diff, tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&worker->dsps1440, diff, tdiff, 86400); |
|
|
|
|
|
|
|
copy_tv(&worker->last_share, &now_t); |
|
|
|
copy_tv(&worker->last_share, &now_t); |
|
|
|
worker->idle = false; |
|
|
|
worker->idle = false; |
|
|
|
|
|
|
|
|
|
|
|
tdiff = sane_tdiff(&now_t, &user->last_share); |
|
|
|
decay_user(user, diff, &now_t); |
|
|
|
decay_time(&user->dsps1, diff, tdiff, 60); |
|
|
|
|
|
|
|
decay_time(&user->dsps5, diff, tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&user->dsps60, diff, tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&user->dsps1440, diff, tdiff, 86400); |
|
|
|
|
|
|
|
decay_time(&user->dsps10080, diff, tdiff, 604800); |
|
|
|
|
|
|
|
copy_tv(&user->last_share, &now_t); |
|
|
|
copy_tv(&user->last_share, &now_t); |
|
|
|
client->idle = false; |
|
|
|
client->idle = false; |
|
|
|
|
|
|
|
|
|
|
@ -3302,17 +3450,13 @@ static json_params_t |
|
|
|
|
|
|
|
|
|
|
|
static void set_worker_mindiff(ckpool_t *ckp, const char *workername, int mindiff) |
|
|
|
static void set_worker_mindiff(ckpool_t *ckp, const char *workername, int mindiff) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *username = strdupa(workername), *ignore; |
|
|
|
|
|
|
|
stratum_instance_t *client; |
|
|
|
stratum_instance_t *client; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
sdata_t *sdata = ckp->data; |
|
|
|
worker_instance_t *worker; |
|
|
|
worker_instance_t *worker; |
|
|
|
user_instance_t *user; |
|
|
|
user_instance_t *user; |
|
|
|
|
|
|
|
|
|
|
|
ignore = username; |
|
|
|
|
|
|
|
strsep(&ignore, "._"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Find the user first */ |
|
|
|
/* Find the user first */ |
|
|
|
user = get_user(sdata, username); |
|
|
|
user = user_by_workername(sdata, workername); |
|
|
|
|
|
|
|
|
|
|
|
/* Then find the matching worker user */ |
|
|
|
/* Then find the matching worker user */ |
|
|
|
worker = get_worker(sdata, user, workername); |
|
|
|
worker = get_worker(sdata, user, workername); |
|
|
@ -4110,11 +4254,7 @@ static void *statsupdate(void *arg) |
|
|
|
/* Decay times per connected instance */ |
|
|
|
/* Decay times per connected instance */ |
|
|
|
if (per_tdiff > 60) { |
|
|
|
if (per_tdiff > 60) { |
|
|
|
/* No shares for over a minute, decay to 0 */ |
|
|
|
/* No shares for over a minute, decay to 0 */ |
|
|
|
decay_time(&client->dsps1, 0, per_tdiff, 60); |
|
|
|
decay_client(client, 0, &now); |
|
|
|
decay_time(&client->dsps5, 0, per_tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&client->dsps60, 0, per_tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&client->dsps1440, 0, per_tdiff, 86400); |
|
|
|
|
|
|
|
decay_time(&client->dsps10080, 0, per_tdiff, 604800); |
|
|
|
|
|
|
|
idle_workers++; |
|
|
|
idle_workers++; |
|
|
|
if (per_tdiff > 600) |
|
|
|
if (per_tdiff > 600) |
|
|
|
client->idle = true; |
|
|
|
client->idle = true; |
|
|
@ -4133,10 +4273,7 @@ static void *statsupdate(void *arg) |
|
|
|
DL_FOREACH(user->worker_instances, worker) { |
|
|
|
DL_FOREACH(user->worker_instances, worker) { |
|
|
|
per_tdiff = tvdiff(&now, &worker->last_share); |
|
|
|
per_tdiff = tvdiff(&now, &worker->last_share); |
|
|
|
if (per_tdiff > 60) { |
|
|
|
if (per_tdiff > 60) { |
|
|
|
decay_time(&worker->dsps1, 0, per_tdiff, 60); |
|
|
|
decay_worker(worker, 0, &now); |
|
|
|
decay_time(&worker->dsps5, 0, per_tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&worker->dsps60, 0, per_tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&worker->dsps1440, 0, per_tdiff, 86400); |
|
|
|
|
|
|
|
worker->idle = true; |
|
|
|
worker->idle = true; |
|
|
|
} |
|
|
|
} |
|
|
|
ghs = worker->dsps1 * nonces; |
|
|
|
ghs = worker->dsps1 * nonces; |
|
|
@ -4151,14 +4288,19 @@ static void *statsupdate(void *arg) |
|
|
|
ghs = worker->dsps1440 * nonces; |
|
|
|
ghs = worker->dsps1440 * nonces; |
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
suffix_string(ghs, suffix1440, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ghs = worker->dsps10080 * nonces; |
|
|
|
|
|
|
|
suffix_string(ghs, suffix10080, 16, 0); |
|
|
|
|
|
|
|
|
|
|
|
copy_tv(&worker->last_update, &now); |
|
|
|
copy_tv(&worker->last_update, &now); |
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,si,sf}", |
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,sI,sf}", |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1d", suffix1440, |
|
|
|
"hashrate1d", suffix1440, |
|
|
|
|
|
|
|
"hashrate7d", suffix10080, |
|
|
|
"lastupdate", now.tv_sec, |
|
|
|
"lastupdate", now.tv_sec, |
|
|
|
|
|
|
|
"shares", worker->shares, |
|
|
|
"bestshare", worker->best_diff); |
|
|
|
"bestshare", worker->best_diff); |
|
|
|
|
|
|
|
|
|
|
|
ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); |
|
|
|
ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); |
|
|
@ -4170,11 +4312,7 @@ static void *statsupdate(void *arg) |
|
|
|
/* Decay times per user */ |
|
|
|
/* Decay times per user */ |
|
|
|
per_tdiff = tvdiff(&now, &user->last_share); |
|
|
|
per_tdiff = tvdiff(&now, &user->last_share); |
|
|
|
if (per_tdiff > 60) { |
|
|
|
if (per_tdiff > 60) { |
|
|
|
decay_time(&user->dsps1, 0, per_tdiff, 60); |
|
|
|
decay_user(user, 0, &now); |
|
|
|
decay_time(&user->dsps5, 0, per_tdiff, 300); |
|
|
|
|
|
|
|
decay_time(&user->dsps60, 0, per_tdiff, 3600); |
|
|
|
|
|
|
|
decay_time(&user->dsps1440, 0, per_tdiff, 86400); |
|
|
|
|
|
|
|
decay_time(&user->dsps10080, 0, per_tdiff, 604800); |
|
|
|
|
|
|
|
idle = true; |
|
|
|
idle = true; |
|
|
|
} |
|
|
|
} |
|
|
|
ghs = user->dsps1 * nonces; |
|
|
|
ghs = user->dsps1 * nonces; |
|
|
@ -4194,7 +4332,7 @@ static void *statsupdate(void *arg) |
|
|
|
|
|
|
|
|
|
|
|
copy_tv(&user->last_update, &now); |
|
|
|
copy_tv(&user->last_update, &now); |
|
|
|
|
|
|
|
|
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,si,sf}", |
|
|
|
JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,si,sI,sf}", |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate1m", suffix1, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate5m", suffix5, |
|
|
|
"hashrate1hr", suffix60, |
|
|
|
"hashrate1hr", suffix60, |
|
|
@ -4202,6 +4340,7 @@ static void *statsupdate(void *arg) |
|
|
|
"hashrate7d", suffix10080, |
|
|
|
"hashrate7d", suffix10080, |
|
|
|
"lastupdate", now.tv_sec, |
|
|
|
"lastupdate", now.tv_sec, |
|
|
|
"workers", user->workers, |
|
|
|
"workers", user->workers, |
|
|
|
|
|
|
|
"shares", user->shares, |
|
|
|
"bestshare", user->best_diff); |
|
|
|
"bestshare", user->best_diff); |
|
|
|
|
|
|
|
|
|
|
|
ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username); |
|
|
|
ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username); |
|
|
@ -4323,18 +4462,18 @@ static void *statsupdate(void *arg) |
|
|
|
stats->accounted_diff_shares += stats->unaccounted_diff_shares; |
|
|
|
stats->accounted_diff_shares += stats->unaccounted_diff_shares; |
|
|
|
stats->accounted_rejects += stats->unaccounted_rejects; |
|
|
|
stats->accounted_rejects += stats->unaccounted_rejects; |
|
|
|
|
|
|
|
|
|
|
|
decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, 60); |
|
|
|
decay_time(&stats->sps1, stats->unaccounted_shares, 1.875, MIN1); |
|
|
|
decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, 300); |
|
|
|
decay_time(&stats->sps5, stats->unaccounted_shares, 1.875, MIN5); |
|
|
|
decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, 900); |
|
|
|
decay_time(&stats->sps15, stats->unaccounted_shares, 1.875, MIN15); |
|
|
|
decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, 3600); |
|
|
|
decay_time(&stats->sps60, stats->unaccounted_shares, 1.875, HOUR); |
|
|
|
|
|
|
|
|
|
|
|
decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, 60); |
|
|
|
decay_time(&stats->dsps1, stats->unaccounted_diff_shares, 1.875, MIN1); |
|
|
|
decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, 300); |
|
|
|
decay_time(&stats->dsps5, stats->unaccounted_diff_shares, 1.875, MIN5); |
|
|
|
decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, 900); |
|
|
|
decay_time(&stats->dsps15, stats->unaccounted_diff_shares, 1.875, MIN15); |
|
|
|
decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, 3600); |
|
|
|
decay_time(&stats->dsps60, stats->unaccounted_diff_shares, 1.875, HOUR); |
|
|
|
decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, 21600); |
|
|
|
decay_time(&stats->dsps360, stats->unaccounted_diff_shares, 1.875, HOUR6); |
|
|
|
decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, 86400); |
|
|
|
decay_time(&stats->dsps1440, stats->unaccounted_diff_shares, 1.875, DAY); |
|
|
|
decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, 604800); |
|
|
|
decay_time(&stats->dsps10080, stats->unaccounted_diff_shares, 1.875, WEEK); |
|
|
|
|
|
|
|
|
|
|
|
stats->unaccounted_shares = |
|
|
|
stats->unaccounted_shares = |
|
|
|
stats->unaccounted_diff_shares = |
|
|
|
stats->unaccounted_diff_shares = |
|
|
@ -4453,18 +4592,18 @@ static void read_poolstats(ckpool_t *ckp) |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
if (tvsec_diff > 60) { |
|
|
|
LOGNOTICE("Old pool stats indicate pool down for %d seconds, decaying stats", |
|
|
|
LOGNOTICE("Old pool stats indicate pool down for %d seconds, decaying stats", |
|
|
|
tvsec_diff); |
|
|
|
tvsec_diff); |
|
|
|
decay_time(&stats->sps1, 0, tvsec_diff, 60); |
|
|
|
decay_time(&stats->sps1, 0, tvsec_diff, MIN1); |
|
|
|
decay_time(&stats->sps5, 0, tvsec_diff, 300); |
|
|
|
decay_time(&stats->sps5, 0, tvsec_diff, MIN5); |
|
|
|
decay_time(&stats->sps15, 0, tvsec_diff, 900); |
|
|
|
decay_time(&stats->sps15, 0, tvsec_diff, MIN15); |
|
|
|
decay_time(&stats->sps60, 0, tvsec_diff, 3600); |
|
|
|
decay_time(&stats->sps60, 0, tvsec_diff, HOUR); |
|
|
|
|
|
|
|
|
|
|
|
decay_time(&stats->dsps1, 0, tvsec_diff, 60); |
|
|
|
decay_time(&stats->dsps1, 0, tvsec_diff, MIN1); |
|
|
|
decay_time(&stats->dsps5, 0, tvsec_diff, 300); |
|
|
|
decay_time(&stats->dsps5, 0, tvsec_diff, MIN5); |
|
|
|
decay_time(&stats->dsps15, 0, tvsec_diff, 900); |
|
|
|
decay_time(&stats->dsps15, 0, tvsec_diff, MIN15); |
|
|
|
decay_time(&stats->dsps60, 0, tvsec_diff, 3600); |
|
|
|
decay_time(&stats->dsps60, 0, tvsec_diff, HOUR); |
|
|
|
decay_time(&stats->dsps360, 0, tvsec_diff, 21600); |
|
|
|
decay_time(&stats->dsps360, 0, tvsec_diff, HOUR6); |
|
|
|
decay_time(&stats->dsps1440, 0, tvsec_diff, 86400); |
|
|
|
decay_time(&stats->dsps1440, 0, tvsec_diff, DAY); |
|
|
|
decay_time(&stats->dsps10080, 0, tvsec_diff, 604800); |
|
|
|
decay_time(&stats->dsps10080, 0, tvsec_diff, WEEK); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|