From b5421746346af32bd300443356865d8910193edd Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 21 Aug 2015 12:07:41 +1000 Subject: [PATCH 01/27] php - add a comment about case sensitivity when registering --- pool/page_reg.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pool/page_reg.php b/pool/page_reg.php index 66af608d..1b84b0da 100644 --- a/pool/page_reg.php +++ b/pool/page_reg.php @@ -65,7 +65,8 @@ function doregres($data, $u)
* All fields are required
Your Username can't be a BTC address
-
". passrequires() . " +
Note: your username is upper/lowercase sensitive,
+and you must also have upper/lowercase correct on all your miners

" . passrequires() . "
"; From b249e220e2e9d172b49a3a9f95153035e338640a Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 21 Aug 2015 12:19:43 +1000 Subject: [PATCH 02/27] ckdb - update reload comment - we reload everything --- src/ckdb.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 263b4b70..df788315 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -36,30 +36,7 @@ * much larger DB tables so that ckdb is effectively ready for messages * almost immediately * The first ckpool message allows us to know where ckpool is up to - * in the CCLs and thus where to stop processing the CCLs to stay in - * sync with ckpool - * If ckpool isn't running, then the reload will complete at the end of - * the last CCL file, however if the 1st message arrives from ckpool while - * processing the CCLs, that will mark the point where to stop processing - * but can also produce a fatal error at the end of processing, reporting - * the ckpool message, if the message was not found in the CCL processing - * after the message was received - * This can be caused by two circumstances: - * 1) the disk had not yet written it to the CCL when ckdb read EOF and - * ckpool was started at about the same time as the reload completed. - * This can be seen if the message displayed in the fatal error IS NOT - * in ckdb's message logfile. - * A ckdb restart will resolve this - * 2) ckpool was started at the time of the end of the reload, but the - * message was written to disk and found in the CCL before it was - * processed in the message queue. - * This can be seen if the message displayed in the fatal error IS in - * ckdb's message logfile and means the messages after it in ckdb's - * message logfile have already been processed. - * Again, a ckdb restart will resolve this - * In both the above (very rare) cases, if ckdb was to continue running, - * it would break the synchronisation and could cause DB problems, so - * ckdb aborting and needing a complete restart resolves it + * in the CCLs - see reload_from() for how this is handled * The users table, required for the authorise messages, is always updated * immediately */ From bab658e03eabd955ee911898e5d2252f562fbd69 Mon Sep 17 00:00:00 2001 From: kanoi Date: Fri, 21 Aug 2015 15:05:28 +1000 Subject: [PATCH 03/27] ckdb - allow changing the btc server via the socket --- src/ckdb.c | 4 ++++ src/ckdb.h | 5 ++++- src/ckdb_btc.c | 2 ++ src/ckdb_cmd.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/ckdb.c b/src/ckdb.c index df788315..50eaac49 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -278,6 +278,7 @@ static sem_t socketer_sem; char *btc_server = "http://127.0.0.1:8330"; char *btc_auth; int btc_timeout = 5; +cklock_t btc_lock; char *by_default = "code"; char *inet_default = "127.0.0.1"; @@ -3935,6 +3936,7 @@ static void *socketer(__maybe_unused void *arg) case CMD_USERSTATUS: case CMD_SHSTA: case CMD_USERINFO: + case CMD_BTCSET: ans = ckdb_cmds[msgline->which_cmds].func(NULL, msgline->cmd, msgline->id, @@ -4274,6 +4276,7 @@ static void reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) case CMD_PSHIFT: case CMD_SHSTA: case CMD_USERINFO: + case CMD_BTCSET: LOGERR("%s() INVALID message line %"PRIu64 " ignored '%.42s...", __func__, count, @@ -5587,6 +5590,7 @@ int main(int argc, char **argv) ckp.main.processname = strdup("main"); cklock_init(&last_lock); + cklock_init(&btc_lock); cklock_init(&seq_lock); cklock_init(&process_pplns_lock); diff --git a/src/ckdb.h b/src/ckdb.h index a1f713bc..a6f94404 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.222" +#define CKDB_VERSION DB_VERSION"-1.223" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -335,6 +335,8 @@ extern cklock_t last_lock; extern char *btc_server; extern char *btc_auth; extern int btc_timeout; +// Lock access to the above variables so they can be changed +extern cklock_t btc_lock; #define EDDB "expirydate" #define CDDB "createdate" @@ -401,6 +403,7 @@ enum cmd_values { CMD_PSHIFT, CMD_SHSTA, CMD_USERINFO, + CMD_BTCSET, CMD_END }; diff --git a/src/ckdb_btc.c b/src/ckdb_btc.c index 44105190..93759bc2 100644 --- a/src/ckdb_btc.c +++ b/src/ckdb_btc.c @@ -32,9 +32,11 @@ static char *btc_data(char *json, size_t *len) APPEND_REALLOC_INIT(buf, off, *len); APPEND_REALLOC(buf, off, *len, "POST / HTTP/1.1\n"); + ck_wlock(&btc_lock); snprintf(tmp, sizeof(tmp), "Authorization: Basic %s\n", btc_auth); APPEND_REALLOC(buf, off, *len, tmp); snprintf(tmp, sizeof(tmp), "Host: %s/\n", btc_server); + ck_wunlock(&btc_lock); APPEND_REALLOC(buf, off, *len, tmp); APPEND_REALLOC(buf, off, *len, "Content-Type: application/json\n"); snprintf(tmp, sizeof(tmp), "Content-Length: %d\n\n", (int)strlen(json)); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 774a018c..64008c6e 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -6300,6 +6300,60 @@ static char *cmd_userinfo(__maybe_unused PGconn *conn, char *cmd, char *id, return buf; } +/* Set/show the BTC server settings + * You must supply the btcserver to change anything + * The format for userpass is username:password + * If you don't supply the btcserver it will simply report the current server + * If supply btcserver but not the userpass it will use the current userpass + * The reply will ONLY contain the URL, not the user/pass */ +static char *cmd_btcset(__maybe_unused PGconn *conn, char *cmd, char *id, + __maybe_unused tv_t *now, __maybe_unused char *by, + __maybe_unused char *code, __maybe_unused char *inet, + __maybe_unused tv_t *notcd, K_TREE *trf_root) +{ + K_ITEM *i_btcserver, *i_userpass; + char *btcserver = NULL, *userpass = NULL, *tmp; + char reply[1024] = ""; + size_t siz = sizeof(reply); + char buf[256]; + + i_btcserver = optional_name(trf_root, "btcserver", 1, NULL, reply, siz); + if (i_btcserver) { + btcserver = strdup(transfer_data(i_btcserver)); + i_userpass = optional_name(trf_root, "userpass", 0, NULL, reply, siz); + if (i_userpass) + userpass = transfer_data(i_userpass); + + ck_wlock(&btc_lock); + btc_server = btcserver; + btcserver = NULL; + if (userpass) { + if (btc_auth) { + tmp = btc_auth; + while (*tmp) + *(tmp++) = '\0'; + } + FREENULL(btc_auth); + btc_auth = http_base64(userpass); + } + ck_wunlock(&btc_lock); + + if (userpass) { + tmp = userpass; + while (*tmp) + *(tmp++) = '\0'; + } + } + + FREENULL(btcserver); + + ck_wlock(&btc_lock); + snprintf(buf, sizeof(buf), "ok.btcserver=%s", btc_server); + ck_wunlock(&btc_lock); + LOGDEBUG("%s.%s.%s", id, cmd, buf); + return strdup(buf); +} + // TODO: limit access by having seperate sockets for each #define ACCESS_POOL "p" #define ACCESS_SYSTEM "s" @@ -6414,5 +6468,6 @@ struct CMDS ckdb_cmds[] = { { CMD_PSHIFT, "pshift", false, false, cmd_pshift, SEQ_NONE, ACCESS_SYSTEM ACCESS_WEB }, { CMD_SHSTA, "shsta", true, false, cmd_shsta, SEQ_NONE, ACCESS_SYSTEM }, { CMD_USERINFO, "userinfo", false, false, cmd_userinfo, SEQ_NONE, ACCESS_WEB }, + { CMD_BTCSET, "btcset", false, false, cmd_btcset, SEQ_NONE, ACCESS_SYSTEM }, { CMD_END, NULL, false, false, NULL, SEQ_NONE, NULL } }; From 53ba32c29790535b86cb9d2f876348f9e1464d2b Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 22 Aug 2015 21:25:49 +1000 Subject: [PATCH 04/27] ckdb/php - allow matching a group of workers with the shift graph --- pool/page_usperf.php | 3 +- src/ckdb.h | 2 +- src/ckdb_cmd.c | 208 +++++++++++++++++++------------------------ 3 files changed, 97 insertions(+), 116 deletions(-) diff --git a/pool/page_usperf.php b/pool/page_usperf.php index f16030a6..a28a48c9 100644 --- a/pool/page_usperf.php +++ b/pool/page_usperf.php @@ -72,7 +72,8 @@ function dousperf($data, $user) $pg .= '
'; $tt = "
  • all = all workers
  • noname = worker with no workername
  • "; - $tt .= "
  • or full workername without the username i.e. .worker or _worker
"; + $tt .= "
  • or full workername without the username i.e. .worker or _worker
  • "; + $tt .= "
  • add a '*' on the end to match multiple workers e.g. .S3*
  • "; $pg .= "?"; $pg .= "$tt"; diff --git a/src/ckdb.h b/src/ckdb.h index a6f94404..8c62f405 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.223" +#define CKDB_VERSION DB_VERSION"-1.224" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 64008c6e..bc96c1f9 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -5037,15 +5037,16 @@ static char *cmd_mpayouts(__maybe_unused PGconn *conn, char *cmd, char *id, return buf; } -/* Find the offset, in list, of the workername - * -1 means NULL list, empty list or not found */ -static int worker_offset(char **list, char *workername) +typedef struct worker_match { + char *worker; + bool match; + size_t len; + bool used; +} WM; + +static char *worker_offset(char *workername) { char *c1, *c2; - int i; - - if (!list || !(*list)) - return -1; /* Find the start of the workername including the SEP */ c1 = strchr(workername, WORKSEP1); @@ -5057,11 +5058,8 @@ static int worker_offset(char **list, char *workername) // No workername after the username if (!c1) c1 = WORKERS_EMPTY; - for (i = 0; list[i]; i++) { - if (strcmp(c1, list[i]) == 0) - return i; - } - return -1; + + return c1; } /* Some arbitrarily large limit, increase it if needed @@ -5069,28 +5067,19 @@ static int worker_offset(char **list, char *workername) #define SELECT_LIMIT 63 /* select is a string of workernames separated by WORKERS_SEL_SEP - * Return an array of strings of select broken up - * The array is terminated by NULL + * Setup the wm array of workers with select broken up + * The wm array is terminated by workers = NULL * and will have 0 elements if select is NULL/empty - * The count of the first occurrence of WORKERS_ALL is returned in *all_count, + * The count of the first occurrence of WORKERS_ALL is returned, * or -1 if WORKERS_ALL isn't found */ -static char **select_list(char *select, int *all_count) +static int select_list(WM *wm, char *select) { - size_t len, offset, siz; - char **list = NULL; - int count; + int count, all_count = -1; + size_t len, offset; char *end; - *all_count = -1; - - siz = sizeof(char *) * (SELECT_LIMIT + 1); - list = malloc(siz); - if (!list) - quithere(1, "malloc (%d) OOM", (int)siz); - list[0] = NULL; - if (select == NULL || *select == '\0') - return list; + return all_count; len = strlen(select); count = 0; @@ -5099,24 +5088,24 @@ static char **select_list(char *select, int *all_count) if (select[offset] == WORKERS_SEL_SEP) offset++; else { - list[count] = select + offset; - list[count+1] = NULL; - end = strchr(list[count], WORKERS_SEL_SEP); + wm[count].worker = select + offset; + wm[count+1].worker = NULL; + end = strchr(wm[count].worker, WORKERS_SEL_SEP); if (end != NULL) { offset = 1 + end - select; *end = '\0'; } - if (*all_count == -1 && - strcasecmp(list[count], WORKERS_ALL) == 0) { - *all_count = count; + if (all_count == -1 && + strcasecmp(wm[count].worker, WORKERS_ALL) == 0) { + all_count = count; } if (end == NULL || ++count > SELECT_LIMIT) break; } } - return list; + return all_count; } static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, @@ -5129,7 +5118,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, K_TREE_CTX wm_ctx[1], ms_ctx[1]; WORKMARKERS *wm; WORKINFO *wi; - MARKERSUMMARY markersummary, *ms, ms_add; + MARKERSUMMARY markersummary, *ms, ms_add[SELECT_LIMIT+1]; PAYOUTS *payouts; USERS *users; MARKS *marks = NULL; @@ -5137,9 +5126,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, char tmp[1024]; size_t siz = sizeof(reply); char *select = NULL; - char **selects = NULL; - bool used[SELECT_LIMIT]; - char *buf; + WM workm[SELECT_LIMIT+1]; + char *buf, *work; size_t len, off; tv_t marker_end = { 0L, 0L }; int rows, want, i, where_all; @@ -5177,17 +5165,27 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, if (i_select) select = strdup(transfer_data(i_select)); - selects = select_list(select, &where_all); + bzero(workm, sizeof(workm)); + where_all = select_list(&(workm[0]), select); // Nothing selected = all - if (*selects == NULL) { + if (workm[0].worker == NULL) { where_all = 0; - selects[0] = WORKERS_ALL; - selects[1] = NULL; + workm[0].worker = WORKERS_ALL; + } else { + for (i = 0; workm[i].worker; i++) { + // N.B. len is only used if match is true + len = workm[i].len = strlen(workm[i].worker); + // If at least 3 characters and last is '*' + if (len > 2 && workm[i].worker[len-1] == '*') { + workm[i].worker[len-1] = '\0'; + workm[i].match = true; + workm[i].len--; + } + } } - bzero(used, sizeof(used)); if (where_all >= 0) - used[where_all] = true; + workm[where_all].used = true; APPEND_REALLOC_INIT(buf, off, len); APPEND_REALLOC(buf, off, len, "ok."); @@ -5216,7 +5214,12 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, wm->workinfoidend); } - bzero(&ms_add, sizeof(ms_add)); + // Zero everything for this shift + bzero(ms_add, sizeof(ms_add)); + for (i = 0; workm[i].worker; i++) { + if (i != where_all) + workm[i].used = false; + } markersummary.markerid = wm->markerid; markersummary.userid = users->userid; @@ -5227,49 +5230,56 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, DATA_MARKERSUMMARY_NULL(ms, ms_item); while (ms_item && ms->markerid == wm->markerid && ms->userid == users->userid) { - ms_add.diffacc += ms->diffacc; - ms_add.diffsta += ms->diffsta; - ms_add.diffdup += ms->diffdup; - ms_add.diffhi += ms->diffhi; - ms_add.diffrej += ms->diffrej; - ms_add.shareacc += ms->shareacc; - ms_add.sharesta += ms->sharesta; - ms_add.sharedup += ms->sharedup; - ms_add.sharehi += ms->sharehi; - ms_add.sharerej += ms->sharerej; - - want = worker_offset(selects, ms->workername); - if (want >= 0) { - used[want] = true; - double_to_buf(ms->diffacc, reply, sizeof(reply)); + work = worker_offset(ms->workername); + for (want = 0; workm[want].worker; want++) { + if ((want == where_all) || + (workm[want].match && strncmp(work, workm[want].worker, workm[want].len) == 0) || + (!(workm[want].match) && strcmp(workm[want].worker, work) == 0)) { + workm[want].used = true; + ms_add[want].diffacc += ms->diffacc; + ms_add[want].diffsta += ms->diffsta; + ms_add[want].diffdup += ms->diffdup; + ms_add[want].diffhi += ms->diffhi; + ms_add[want].diffrej += ms->diffrej; + ms_add[want].shareacc += ms->shareacc; + ms_add[want].sharesta += ms->sharesta; + ms_add[want].sharedup += ms->sharedup; + ms_add[want].sharehi += ms->sharehi; + ms_add[want].sharerej += ms->sharerej; + } + } + ms_item = next_in_ktree(ms_ctx); + DATA_MARKERSUMMARY_NULL(ms, ms_item); + } + K_RUNLOCK(markersummary_free); + + for (i = 0; i <= SELECT_LIMIT; i++) { + if (workm[i].used) { + double_to_buf(ms_add[i].diffacc, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "%d_diffacc:%d=%s%c", - want, rows, reply, FLDSEP); + i, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - d = ms->diffsta + ms->diffdup + - ms->diffhi + ms->diffrej; + d = ms_add[i].diffsta + ms_add[i].diffdup + + ms_add[i].diffhi + ms_add[i].diffrej; double_to_buf(d, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "%d_diffinv:%d=%s%c", - want, rows, reply, FLDSEP); + i, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - double_to_buf(ms->shareacc, reply, sizeof(reply)); + double_to_buf(ms_add[i].shareacc, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "%d_shareacc:%d=%s%c", - want, rows, reply, FLDSEP); + i, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - d = ms->sharesta + ms->sharedup + - ms->sharehi + ms->sharerej; + d = ms_add[i].sharesta + ms_add[i].sharedup + + ms_add[i].sharehi + ms_add[i].sharerej; double_to_buf(d, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "%d_shareinv:%d=%s%c", - want, rows, reply, FLDSEP); + i, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); } - - ms_item = next_in_ktree(ms_ctx); - DATA_MARKERSUMMARY_NULL(ms, ms_item); } - K_RUNLOCK(markersummary_free); if (marker_end.tv_sec == 0L) { wi_item = next_workinfo(wm->workinfoidend, NULL); @@ -5286,7 +5296,6 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, wm->workinfoidend); snprintf(reply, siz, "data error 1"); free(buf); - free(selects); return(strdup(reply)); } DATA_WORKINFO(wi, wi_item); @@ -5307,7 +5316,6 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, wm->workinfoidstart); snprintf(reply, siz, "data error 2"); free(buf); - free(selects); return(strdup(reply)); } DATA_WORKINFO(wi, wi_item); @@ -5338,35 +5346,6 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - if (where_all >= 0) { - double_to_buf(ms_add.diffacc, reply, sizeof(reply)); - snprintf(tmp, sizeof(tmp), "%d_diffacc:%d=%s%c", - where_all, rows, - reply, FLDSEP); - APPEND_REALLOC(buf, off, len, tmp); - - d = ms_add.diffsta + ms_add.diffdup + - ms_add.diffhi + ms_add.diffrej; - double_to_buf(d, reply, sizeof(reply)); - snprintf(tmp, sizeof(tmp), "%d_diffinv:%d=%s%c", - where_all, rows, - reply, FLDSEP); - APPEND_REALLOC(buf, off, len, tmp); - - double_to_buf(ms_add.shareacc, reply, sizeof(reply)); - snprintf(tmp, sizeof(tmp), "%d_shareacc:%d=%s%c", - where_all, rows, - reply, FLDSEP); - APPEND_REALLOC(buf, off, len, tmp); - - d = ms_add.sharesta + ms_add.sharedup + - ms_add.sharehi + ms_add.sharerej; - double_to_buf(d, reply, sizeof(reply)); - snprintf(tmp, sizeof(tmp), "%d_shareinv:%d=%s%c", - where_all, rows, - reply, FLDSEP); - APPEND_REALLOC(buf, off, len, tmp); - } rows++; // Setup for next shift @@ -5379,11 +5358,13 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, } K_RUNLOCK(workmarkers_free); - for (i = 0; selects[i]; i++) { - if (used[i]) { + for (i = 0; workm[i].worker; i++) { + if (workm[i].used) { snprintf(tmp, sizeof(tmp), - "%d_worker=%s%c", - i, selects[i], FLDSEP); + "%d_worker=%s%s%c", + i, workm[i].worker, + workm[i].match ? "*" : EMPTY, + FLDSEP); APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "%d_flds=%s%c", i, @@ -5409,8 +5390,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts"); APPEND_REALLOC(buf, off, len, tmp); - for (i = 0; selects[i]; i++) { - if (used[i]) { + for (i = 0; workm[i].worker; i++) { + if (workm[i].used) { snprintf(tmp, sizeof(tmp), ",Worker_%d", i); APPEND_REALLOC(buf, off, len, tmp); } @@ -5418,15 +5399,14 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "%carp=", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - for (i = 0; selects[i]; i++) { - if (used[i]) { + for (i = 0; workm[i].worker; i++) { + if (workm[i].used) { snprintf(tmp, sizeof(tmp), ",%d_", i); APPEND_REALLOC(buf, off, len, tmp); } } LOGDEBUG("%s.ok.%s", id, transfer_data(i_username)); - free(selects); return(buf); } From 543c5e70821c48d1de4c3ea3960b872730a798cc Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 22 Aug 2015 22:17:19 +1000 Subject: [PATCH 05/27] ckdb - add optioncontrol override for blocklist rows --- src/ckdb.h | 7 ++++++- src/ckdb_cmd.c | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 8c62f405..1038b5a0 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.224" +#define CKDB_VERSION DB_VERSION"-1.225" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1548,6 +1548,11 @@ extern K_STORE *blocks_store; extern tv_t blocks_stats_time; extern bool blocks_stats_rebuild; +// Default number of blocks to display on web +#define BLOCKS_DEFAULT 42 +// OptionControl can override it +#define BLOCKS_SETTING_NAME "BlocksPageSize" + // MININGPAYOUTS typedef struct miningpayouts { int64_t payoutid; diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index bc96c1f9..fe03ab59 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -1116,7 +1116,7 @@ static char *cmd_workerstats(__maybe_unused PGconn *conn, char *cmd, char *id, } static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, - __maybe_unused tv_t *now, __maybe_unused char *by, + tv_t *now, __maybe_unused char *by, __maybe_unused char *code, __maybe_unused char *inet, __maybe_unused tv_t *notcd, __maybe_unused K_TREE *trf_root) @@ -1131,10 +1131,14 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, int32_t height = -1; tv_t first_cd = {0,0}, stats_tv = {0,0}, stats_tv2 = {0,0}; int rows, srows, tot, seq; + int64_t maxrows; bool has_stats; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + // 0 means just the system setting + maxrows = user_sys_setting(0, BLOCKS_SETTING_NAME, BLOCKS_DEFAULT, now); + APPEND_REALLOC_INIT(buf, off, len); APPEND_REALLOC(buf, off, len, "ok."); @@ -1158,7 +1162,7 @@ redo: } seq = tot; b_item = last_in_ktree(blocks_root, ctx); - while (b_item && rows < 42) { + while (b_item && rows < (int)maxrows) { DATA_BLOCKS(blocks, b_item); /* For each block remember the initial createdate * Reverse sort order the oldest expirydate is first From 285c1d309b1d6cc456a85f4d1bb62575efe8bff3 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 22 Aug 2015 22:26:18 +1000 Subject: [PATCH 06/27] ckdb - missing a space in a message --- src/ckdb_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ckdb_data.c b/src/ckdb_data.c index f2c491ee..51ab0396 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -3291,7 +3291,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) if (p_item) { DATA_PAYOUTS(payouts, p_item); tv_to_buf(&(payouts->createdate), cd_buf, sizeof(cd_buf)); - LOGERR("%s(): payout for block %"PRId32"/%s already exists" + LOGERR("%s(): payout for block %"PRId32"/%s already exists " "%"PRId64"/%"PRId64"/%"PRId64"/%s", __func__, height, blockhash, payouts->payoutid, payouts->workinfoidstart, payouts->workinfoidend, From 30376deb94f98ca8c3f124ceac53bcccc9ba4360 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 22 Aug 2015 22:36:20 +1000 Subject: [PATCH 07/27] ckdb - demote successful missing workerstatus/worker messages to notice --- src/ckdb.h | 2 +- src/ckdb_data.c | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 1038b5a0..c0f1eaec 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.225" +#define CKDB_VERSION DB_VERSION"-1.226" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 51ab0396..ab3f5913 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -882,12 +882,17 @@ K_ITEM *_find_create_workerstatus(int64_t userid, char *workername, K_WUNLOCK(workerstatus_free); if (ws_err) { - LOGERR("%s(): CREATED Missing workerstatus %"PRId64"/%s" - WHERE_FFL WHERE_FFL, - __func__, userid, workername, - file2, func2, line2, WHERE_FFL_PASS); + LOGNOTICE("%s(): CREATED Missing workerstatus" + " %"PRId64"/%s" + WHERE_FFL WHERE_FFL, + __func__, userid, workername, + file2, func2, line2, WHERE_FFL_PASS); if (w_err) { - LOGERR("%s(): %s Missing worker %"PRId64"/%s", + int sta = LOG_ERR; + if (w_item) + sta = LOG_NOTICE; + LOGMSG(sta, + "%s(): %s Missing worker %"PRId64"/%s", __func__, w_item ? "CREATED" : "FAILED TO CREATE", userid, workername); From 3977ee14da772c3103421a5735e041ce0d6d8e25 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 23 Aug 2015 20:15:36 +1000 Subject: [PATCH 08/27] ckdb - set default issuer to not match my pool --- src/ckdb_cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index fe03ab59..02ee883e 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -345,7 +345,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, } } if (key) { - char *keystr, *issuer = "Kano"; + char *keystr, *issuer = "KanoCKDB"; char cd_buf[DATE_BUFSIZ]; unsigned char *bin; OPTIONCONTROL *oc; From 8fb4c820c2264f1caa507b0a0f5277190651fcb8 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 24 Aug 2015 08:36:17 +1000 Subject: [PATCH 09/27] php - tickboxes for temporarily hiding graph lines --- pool/inc.php | 4 +++- pool/page_psperf.php | 1 + pool/page_usperf.php | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pool/inc.php b/pool/inc.php index 75d91b97..0d5c89f2 100644 --- a/pool/inc.php +++ b/pool/inc.php @@ -6,6 +6,7 @@ function GBaseJS() function sep(d){ans={};var ar=d.split('\\t');var l=ar.length;for(var i=0;i(zm-0.5)){return(zm-0.5)}return z} function gchx(c,x){return gch(x*c['xm']+c['xo'],c['ctx'].canvas.width)} function gchy(c,y){return gch((1-y)*c['ym']+c['yo'],c['ctx'].canvas.height)} @@ -27,7 +28,7 @@ function gfl(c){c['ctx'].fill()} function gst(c){c['ctx'].stroke()} function gfi(c){gle(c);gst(c)} function gbd(c){gbe(c,0,0);gln(c,1,0);gln(c,1,1);gln(c,0,1);gle(c);gfl(c);gst(c)} -function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av,w,cols){gtso(c,xs,ys);gss(c,'black');glw(c,1.5);gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);glw(c,0.2);var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('1').width;for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');var m=Math.round(0.5+xn/20.0);for(var i=0;i=x0;i-=hrs){var n=dfmt(c,i);var xo=(i-x0)/(x1-x0);if(xo<=1 && c['tkey'] && ((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(xo<=1 && c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}glw(c,1);if(c['smooth']){for(var j=1;j0){gss(c,'red');var y=(av[j-1]-y0)/(y1-y0);gbe(c,0,y);gln(c,1,y);gst(c);var t=''+av[j-1].toFixed(2)+'av';gfz(c,1,y,1,0,t,cols[j-1],'left')}}if(c['tkey']){var col,hrl=c['hrs'].length;for(var i=0;i=x0;i-=hrs){var n=dfmt(c,i);var xo=(i-x0)/(x1-x0);if(xo<=1 && c['tkey'] && ((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(xo<=1 && c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}glw(c,1);if(c['smooth']){for(var j=1;j0 && c['lin'+j]){gss(c,'red');var y=(av[j-1]-y0)/(y1-y0);gbe(c,0,y);gln(c,1,y);gst(c);var t=''+av[j-1].toFixed(2)+'av';gfz(c,1,y,1,0,t,cols[j-1],'left')}}if(c['tkey']){var col,hrl=c['hrs'].length;for(var i=0;ic['xm']){c['ym']=c['xm']}gc2(c)} @@ -36,6 +37,7 @@ function opts(t,i){var e=document.getElementById(i);if(t.checked){e.style.visibi function ghrs(c){c['hrs']=[1,2,3,4,6,8,12,24,48];c['hln']=[1,2,3,4,6]} function ghg(c,dx){var tl=dx/(gchx(c,1)/50)/3600;for(var j=c['hrs'].length-1;j>=0;j--){if(tls){xmin=s}if(xmaxths){ymin=ths}if(ths>ymax)ymax=ths;document.getElementById('worker'+j).value=d[pre+'worker']} @@ -83,7 +84,8 @@ function dousperf($data, $user) foreach ($cols as $col) { $i++; - $pg .= " Worker$i:"; + $pg .= " Worker$i"; + $pg .= ":"; $pg .= " "; if ($i > 1) From 4a66fa3a6f19dd4f0cd221ba05f46c8338d0ae55 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 29 Aug 2015 02:21:18 +1000 Subject: [PATCH 10/27] php - make iDevice single item menus one click --- pool/inc.php | 2 ++ pool/page.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pool/inc.php b/pool/inc.php index 0d5c89f2..ad8819a0 100644 --- a/pool/inc.php +++ b/pool/inc.php @@ -106,9 +106,11 @@ input.tiny {width:0px;height:0px;margin:0px;padding:0px;outline:none;border:0px; #n42 a {color:#fff;text-decoration:none;padding:6px;display:block;} #n42 td {min-width:100px;float:left;vertical-align:top;padding:0px 2px;} #n42 td.navboxr {float:right;} +#n42 td.nav0 {position:relative;} #n42 td.nav {position:relative;} #n42 td.ts {border-width:1px;border-color:#0022ee;border-style:solid none none none;} #n42 div.sub {left:0px;z-index:42;position:absolute;visibility:hidden;} +#n42 td.nav0:hover {background:#0099ee;} #n42 td.nav:hover {background:#0099ee;} #n42 td.nav:hover div.sub {background:#0077ee;visibility:visible;} h1 {margin-top:20px;float:middle;font-size:20px;} diff --git a/pool/page.php b/pool/page.php index 6bae844f..0970a23c 100644 --- a/pool/page.php +++ b/pool/page.php @@ -490,7 +490,7 @@ function pgmenu($menus) $first = false; if ($submenu == $menu) { - $ret .= "".makeLink($item)."$menu"; + $ret .= "".makeLink($item)."$menu"; $ret .= '
    '; continue; } From e7c5d1ec826bf23796b3c9edb890e8205902b6ad Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 29 Aug 2015 20:58:28 +1000 Subject: [PATCH 11/27] ckdb/php - add age to block stats table --- pool/base.php | 48 ++++++++++++++++++++++++++++++++++++++++++++ pool/page_blocks.php | 3 +++ src/ckdb.h | 2 +- src/ckdb_cmd.c | 7 ++++++- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/pool/base.php b/pool/base.php index e388a538..7c88113c 100644 --- a/pool/base.php +++ b/pool/base.php @@ -28,6 +28,54 @@ function dq($str) return str_replace('"', "\\\"", $str); } # +function daysago($val) +{ + if ($val < -13) + return ''; + + if ($val < 60) + $des = $val.'s'; + else + { + $val = round($val/6)/10; + if ($val < 60) + $des = $val.'min'; + else + { + $val = round($val/6)/10; + if ($val < 24) + { + $des = $val.'hr'; + if ($val != 1) + $des .= 's'; + } + else + { + $val = round($val/2.4)/10; + if ($val < 100) + { + $des = $val.'day'; + if ($val != 1) + $des .= 's'; + } + else + { + $val = round($val/0.7)/10; + if ($val < 10000) + { + $des = $val.'wk'; + if ($val != 1) + $des .= 's'; + } + else + $des = ''; + } + } + } + } + return $des; +} +# function howlongago($sec) { if ($sec < 60) diff --git a/pool/page_blocks.php b/pool/page_blocks.php index 68d04704..167f2999 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -93,6 +93,7 @@ function doblocks($data, $user) $pg .= "
    \n"; $pg .= ""; $pg .= ""; + $pg .= ""; $pg .= ""; $pg .= ""; $pg .= ""; @@ -108,6 +109,7 @@ function doblocks($data, $user) $row = 'odd'; $desc = $ans['s_desc:'.$i]; + $age = daysago($ans['STAMP'] - $ans['s_createdate:'.$i]); $diff = number_format(100 * $ans['s_diffratio:'.$i], 2); $mean = number_format(100 * $ans['s_diffmean:'.$i], 2); @@ -120,6 +122,7 @@ function doblocks($data, $user) $pg .= ""; $pg .= ""; + $pg .= ""; $pg .= ""; $pg .= ""; $pg .= ""; diff --git a/src/ckdb.h b/src/ckdb.h index c0f1eaec..b6cfd070 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.226" +#define CKDB_VERSION DB_VERSION"-1.227" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 02ee883e..5f749d3f 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -1303,12 +1303,16 @@ redo: snprintf(tmp, sizeof(tmp), "s_seq:%d=%d%c" "s_desc:%d=%s%c" + "s_height:%d=%d%c" + "s_"CDTRF":%d=%ld%c" "s_diffratio:%d=%.8f%c" "s_diffmean:%d=%.8f%c" "s_cdferl:%d=%.8f%c" "s_luck:%d=%.8f%c", srows, seq, FLDSEP, srows, desc, FLDSEP, + srows, (int)(blocks->height), FLDSEP, + srows, blocks->createdate.tv_sec, FLDSEP, srows, blocks->diffratio, FLDSEP, srows, blocks->diffmean, FLDSEP, srows, blocks->cdferl, FLDSEP, @@ -1340,7 +1344,8 @@ redo: snprintf(tmp, sizeof(tmp), "s_rows=%d%cs_flds=%s%c", srows, FLDSEP, - "s_seq,s_desc,s_diffratio,s_diffmean,s_cdferl,s_luck", + "s_seq,s_desc,s_height,s_"CDTRF",s_diffratio,s_diffmean," + "s_cdferl,s_luck", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); From e9a61d761b3ed77b7996e0eec0f3e884a917e35c Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 29 Aug 2015 21:00:50 +1000 Subject: [PATCH 12/27] ckdb - remove stupid gcc warning --- src/ktree.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/ktree.c b/src/ktree.c index c94d12fb..588683b0 100644 --- a/src/ktree.c +++ b/src/ktree.c @@ -89,15 +89,11 @@ static void show_ktree(K_TREE *root, char *path, int pos, char *(*dsp_funct)(K_I path[pos] = '\0'; - switch(root->red) - { - case RED_RED: + if (root->red == RED_RED) col = 'R'; - break; - case RED_BLACK: + else + // if (root->red == RED_BLACK) col = 'B'; - break; - } printf(" %c %s=%s\n", col, path, dsp_funct(root->data)); From fc51ae29646da93c3f8c9a3f8ddacdae473c24e1 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 29 Aug 2015 22:58:33 +1000 Subject: [PATCH 13/27] ckdb - fix block stat generation error handler typo bug --- src/ckdb.h | 2 +- src/ckdb_data.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index b6cfd070..7db37e9b 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.227" +#define CKDB_VERSION DB_VERSION"-1.228" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_data.c b/src/ckdb_data.c index ab3f5913..6b145163 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -2924,8 +2924,8 @@ bool check_update_blocks_stats(tv_t *stats) K_RUNLOCK(workinfo_free); if (!w_item) { setnow(&now); - if (!blocks->workinfoid != last_missing_workinfoid || - tvdiff(&now, &last_message) >= 5.0) { + if (blocks->workinfoid != last_missing_workinfoid || + tvdiff(&now, &last_message) >= 15.0) { LOGEMERG("%s(): missing block workinfoid %" PRId32"/%"PRId64"/%s", __func__, blocks->height, From df5c372557adec29534bb520c125a9ad4fed4566 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 30 Aug 2015 01:43:34 +1000 Subject: [PATCH 14/27] ckdb/ckp - add reward count to shifts table --- pool/page_shifts.php | 2 ++ src/ckdb.c | 7 +++-- src/ckdb.h | 6 +++- src/ckdb_cmd.c | 12 ++++++- src/ckdb_data.c | 75 ++++++++++++++++++++++++++++++++------------ src/ckdb_dbio.c | 18 ++++++++--- 6 files changed, 92 insertions(+), 28 deletions(-) diff --git a/pool/page_shifts.php b/pool/page_shifts.php index e8efac11..40cc94ff 100644 --- a/pool/page_shifts.php +++ b/pool/page_shifts.php @@ -14,6 +14,7 @@ function doshifts($data, $user) $pg .= ""; $pg .= ""; $pg .= ""; + $pg .= ""; $pg .= "\n"; if (($ans['STATUS'] != 'ok') || !isset($ans['prefix_all'])) @@ -66,6 +67,7 @@ function doshifts($data, $user) else $avgsh = 0; $pg .= ''; + $pg .= ''; $pg .= "\n"; } } diff --git a/src/ckdb.c b/src/ckdb.c index 50eaac49..97b473b7 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -776,8 +776,6 @@ static bool getdata3() goto sukamudai; if (!(ok = miningpayouts_fill(conn)) || everyone_die) goto sukamudai; - if (!(ok = payouts_fill(conn)) || everyone_die) - goto sukamudai; } if (!(ok = workinfo_fill(conn)) || everyone_die) goto sukamudai; @@ -786,6 +784,11 @@ static bool getdata3() /* must be after workinfo */ if (!(ok = workmarkers_fill(conn)) || everyone_die) goto sukamudai; + if (!confirm_sharesummary) { + /* must be after workmarkers */ + if (!(ok = payouts_fill(conn)) || everyone_die) + goto sukamudai; + } if (!(ok = markersummary_fill(conn)) || everyone_die) goto sukamudai; if (!confirm_sharesummary && !everyone_die) diff --git a/src/ckdb.h b/src/ckdb.h index 7db37e9b..8acdd7b1 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -1901,6 +1901,9 @@ typedef struct workmarkers { int64_t workinfoidstart; char *description; char status[TXT_FLAG+1]; + int rewards; // non-DB field + double pps_value; // non-DB field + double rewarded; // non-DB field HISTORYDATECONTROLFIELDS; } WORKMARKERS; @@ -2343,11 +2346,12 @@ extern bool make_markersummaries(bool msg, char *by, char *code, char *inet, extern void dsp_workmarkers(K_ITEM *item, FILE *stream); extern cmp_t cmp_workmarkers(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_workmarkers_workinfoid(K_ITEM *a, K_ITEM *b); -extern K_ITEM *find_workmarkers(int64_t workinfoid, bool anystatus, char status); +extern K_ITEM *find_workmarkers(int64_t workinfoid, bool anystatus, char status, K_TREE_CTX *ctx); extern K_ITEM *find_workmarkerid(int64_t markerid, bool anystatus, char status); extern bool workmarkers_generate(PGconn *conn, char *err, size_t siz, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root, bool none_error); +extern bool reward_shifts(PAYOUTS *payouts, bool lock, int delta); extern cmp_t cmp_marks(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_marks(int64_t workinfoid); extern const char *marks_marktype(char *marktype); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 5f749d3f..1e41f13a 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4789,6 +4789,8 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now, snprintf(reply, siz, "failed payout %"PRId64, payoutid); return strdup(reply); } + // Original wasn't generated, so reward it + reward_shifts(payouts2, true, 1); DATA_PAYOUTS(payouts2, p2_item); DATA_PAYOUTS(old_payouts2, old_p2_item); snprintf(msg, sizeof(msg), @@ -4858,6 +4860,8 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now, snprintf(reply, siz, "failed payout %"PRId64, payoutid); return strdup(reply); } + // Original was generated, so undo the reward + reward_shifts(payouts2, true, -1); DATA_PAYOUTS(payouts2, p2_item); DATA_PAYOUTS(old_payouts2, old_p2_item); snprintf(msg, sizeof(msg), @@ -4875,6 +4879,7 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now, return strdup(reply); TXT_TO_BIGINT("payoutid", transfer_data(i_payoutid), payoutid); + // payouts_full_expire updates the shift rewards p_item = payouts_full_expire(conn, payoutid, now, true); if (!p_item) { snprintf(reply, siz, "failed payout %"PRId64, payoutid); @@ -4911,6 +4916,7 @@ static char *cmd_payouts(PGconn *conn, char *cmd, char *id, tv_t *now, return strdup(reply); TXT_TO_CTV("addrdate", transfer_data(i_addrdate), addrdate); + // process_pplns updates the shift rewards if (addrdate.tv_sec == 0) ok = process_pplns(height, blockhash, NULL); else @@ -5355,6 +5361,10 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "rewards:%d=%d%c", + rows, wm->rewards, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + rows++; // Setup for next shift @@ -5394,7 +5404,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, * other workers start >= 0 and finish <= rows-1 */ snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c", rows, FLDSEP, - "markerid,shift,start,end", FLDSEP); + "markerid,shift,start,end,rewards", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts"); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 6b145163..71754783 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -2070,7 +2070,7 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code, } K_RLOCK(workmarkers_free); - wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED); + wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED, NULL); K_RUNLOCK(workmarkers_free); // Should never happen? if (wm_item && !reloading) { @@ -3589,7 +3589,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) * block - so abort * The fix is to create the marks and summaries needed via * cmd_marks() then manually trigger the payout generation - * TODO: via cmd_payouts() ... which isn't available yet */ + * via cmd_payouts() */ LOGEMERG("%s(): payout had < 1 (%"PRId64") workmarkers for " "block %"PRId32"/%"PRId64"/%s/%s/%"PRId64 " beginwi=%"PRId64" ss=%"PRId64" diff=%.1f", @@ -3810,20 +3810,8 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) pa_item = pa_item->next; } } else { - /* Address user or normal user without a paymentaddress - * TODO: user table needs a flag to say which it is ... - * for now use a simple test */ - bool gotaddr = false; - size_t len; - - switch (users->username[0]) { - case '1': - case '3': - len = strlen(users->username); - if (len >= ADDR_MIN_LEN && len <= ADDR_MAX_LEN) - gotaddr = true; - } - if (gotaddr) { + /* Address user or normal user without a paymentaddress */ + if (users->userbits & USER_ADDRESS) { K_WLOCK(payments_free); pay_item = k_unlink_head(payments_free); K_WUNLOCK(payments_free); @@ -3906,6 +3894,9 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) ss_count, wm_count, ms_count, usercount, diff_times, diff_add, cd_buf); + /* At this point the payout is complete, but it just hasn't been + * flagged complete yet in the DB */ + K_WLOCK(payouts_free); p2_item = k_unlink_head(payouts_free); K_WUNLOCK(payouts_free); @@ -3931,13 +3922,20 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) ok = payouts_add(conn, true, p2_item, &old_p2_item, (char *)by_default, (char *)__func__, (char *)inet_default, &now, NULL, false); + if (!ok) { + /* All that's required is to mark the payout GENERATED + * since it already exists in the DB and in RAM, thus a manual + * cmd_payouts 'generated' is all that's needed to fix it */ LOGEMERG("%s(): payout %"PRId64" for block %"PRId32"/%s " "NOT set generated - it needs to be set manually", __func__, payouts->payoutid, blocks->height, blocks->blockhash); } + // Flag each shift as rewarded + reward_shifts(payouts2, true, 1); + CKPQDisco(&conn, conned); goto oku; @@ -4146,7 +4144,7 @@ K_ITEM *_find_markersummary(int64_t markerid, int64_t workinfoid, K_TREE_CTX ctx[1]; if (markerid == 0) { - wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED); + wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED, NULL); if (wm_item) { DATA_WORKMARKERS(wm, wm_item); markerid = wm->markerid; @@ -4277,12 +4275,15 @@ cmp_t cmp_workmarkers_workinfoid(K_ITEM *a, K_ITEM *b) return c; } -K_ITEM *find_workmarkers(int64_t workinfoid, bool anystatus, char status) +K_ITEM *find_workmarkers(int64_t workinfoid, bool anystatus, char status, K_TREE_CTX *ctx) { WORKMARKERS workmarkers, *wm; - K_TREE_CTX ctx[1]; + K_TREE_CTX ctx0[1]; K_ITEM look, *wm_item; + if (ctx == NULL) + ctx = ctx0; + workmarkers.expirydate.tv_sec = default_expiry.tv_sec; workmarkers.expirydate.tv_usec = default_expiry.tv_usec; workmarkers.workinfoidend = workinfoid-1; @@ -4401,7 +4402,8 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin, * sort order and matching errors */ if (wi_fin->workinfoid >= wi_stt->workinfoid) { K_RLOCK(workmarkers_free); - old_wm_item = find_workmarkers(wi_fin->workinfoid, true, '\0'); + old_wm_item = find_workmarkers(wi_fin->workinfoid, true, '\0', + NULL); K_RUNLOCK(workmarkers_free); DATA_WORKMARKERS_NULL(old_wm, old_wm_item); if (old_wm_item && (WMREADY(old_wm->status) || @@ -4580,6 +4582,39 @@ bool workmarkers_generate(PGconn *conn, char *err, size_t siz, char *by, return true; } +// delta = 1 or -1 i.e. reward or undo reward +bool reward_shifts(PAYOUTS *payouts, bool lock, int delta) +{ + // TODO: PPS calculations + K_TREE_CTX ctx[1]; + K_ITEM *wm_item; + WORKMARKERS *wm; + bool did_one = false; + + if (lock) + K_WLOCK(workmarkers_free); + + wm_item = find_workmarkers(payouts->workinfoidstart, false, + MARKER_PROCESSED, ctx); + while (wm_item) { + DATA_WORKMARKERS(wm, wm_item); + if (wm->workinfoidstart > payouts->workinfoidend) + break; + /* The status doesn't matter since we want the rewards passed + * onto the PROCESSED status if it isn't already processed */ + if (CURRENT(&(wm->expirydate))) { + wm->rewards += delta; + did_one = true; + } + wm_item = next_in_ktree(ctx); + } + + if (lock) + K_WUNLOCK(workmarkers_free); + + return did_one; +} + // order by expirydate asc,workinfoid asc // TODO: add poolinstance cmp_t cmp_marks(K_ITEM *a, K_ITEM *b) diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index f2927d9e..d355be78 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -2959,7 +2959,7 @@ static bool shares_process(PGconn *conn, SHARES *shares, K_TREE *trf_root) if (reloading && !confirm_sharesummary) { // We only need to know if the workmarker is processed wm_item = find_workmarkers(shares->workinfoid, false, - MARKER_PROCESSED); + MARKER_PROCESSED, NULL); if (wm_item) { LOGDEBUG("%s(): workmarker exists for wid %"PRId64 " %"PRId64"/%s/%ld,%ld", @@ -3260,7 +3260,7 @@ static bool shareerrors_process(PGconn *conn, SHAREERRORS *shareerrors, if (reloading && !confirm_sharesummary) { // We only need to know if the workmarker is processed wm_item = find_workmarkers(shareerrors->workinfoid, false, - MARKER_PROCESSED); + MARKER_PROCESSED, NULL); if (wm_item) { LOGDEBUG("%s(): workmarker exists for wid %"PRId64 " %"PRId64"/%s/%ld,%ld", @@ -4024,7 +4024,8 @@ bool _sharesummary_update(SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item, } K_RLOCK(workmarkers_free); - wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED); + wm_item = find_workmarkers(workinfoid, false, MARKER_PROCESSED, + NULL); K_RUNLOCK(workmarkers_free); if (wm_item) { DATA_WORKMARKERS(wm, wm_item); @@ -5465,6 +5466,12 @@ K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, bool lock DATA_PAYMENTS_NULL(payments, pm_item); } + if (PAYGENERATED(payouts->status)) { + // Original was generated, so undo the reward + reward_shifts(payouts, true, -1); + + } + ok = true; matane: if (begun) @@ -5613,6 +5620,9 @@ bool payouts_fill(PGconn *conn) payouts_id_root = add_to_ktree(payouts_id_root, item, cmp_payouts_id); k_add_head(payouts_store, item); + if (CURRENT(&(row->expirydate)) && PAYGENERATED(row->status)) + reward_shifts(row, false, 1); + tick(); } if (!ok) { @@ -6517,7 +6527,7 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add, if (markerid == 0) { K_RLOCK(workmarkers_free); - old_wm_item = find_workmarkers(workinfoidend, true, '\0'); + old_wm_item = find_workmarkers(workinfoidend, true, '\0', NULL); K_RUNLOCK(workmarkers_free); } else { K_RLOCK(workmarkers_free); From 87b8a187f935acba3b0d9a47e19c2de2b5240be9 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 30 Aug 2015 19:23:10 +1000 Subject: [PATCH 15/27] ckdb/php - add a block timestamp to the rewards page --- pool/page_mpayouts.php | 4 +++- src/ckdb.c | 1 + src/ckdb.h | 4 +++- src/ckdb_cmd.c | 7 +++++- src/ckdb_data.c | 50 +++++++++++++++++++++++++++++------------- src/ckdb_dbio.c | 27 ++++++++++++++++++++++- 6 files changed, 74 insertions(+), 19 deletions(-) diff --git a/pool/page_mpayouts.php b/pool/page_mpayouts.php index 18e0df0b..60eec061 100644 --- a/pool/page_mpayouts.php +++ b/pool/page_mpayouts.php @@ -14,6 +14,7 @@ function dompayouts($data, $user) $pg .= "
    DescriptionAgeDiff%Mean%CDF[Erl]
    $desc Blocks$age$diff%$mean%$cdferldspAvg HsSharesAvg ShareRewards
    '.number_format($avgsh, 2).''.$ans['rewards:'.$i].'
    \n"; $pg .= ""; $pg .= ""; + $pg .= ""; $pg .= ""; $pg .= ""; $pg .= ""; @@ -36,6 +37,7 @@ function dompayouts($data, $user) $pg .= ""; $pg .= ''; + $pg .= ''; $pg .= ''; $diffused = $ans['diffused:'.$i]; $pg .= ''; @@ -63,7 +65,7 @@ function dompayouts($data, $user) $pg .= ""; $pg .= ''; - $pg .= ''; + $pg .= ''; $pg .= ''; $pg .= "\n"; } diff --git a/src/ckdb.c b/src/ckdb.c index 97b473b7..4cccaf8c 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -772,6 +772,7 @@ static bool getdata3() if (!confirm_sharesummary) { if (!(ok = paymentaddresses_fill(conn)) || everyone_die) goto sukamudai; + /* FYI must be after blocks */ if (!(ok = payments_fill(conn)) || everyone_die) goto sukamudai; if (!(ok = miningpayouts_fill(conn)) || everyone_die) diff --git a/src/ckdb.h b/src/ckdb.h index 8acdd7b1..8ab5cf26 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.228" +#define CKDB_VERSION DB_VERSION"-1.229" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1578,6 +1578,7 @@ typedef struct payouts { int64_t payoutid; int32_t height; char blockhash[TXT_BIG+1]; + tv_t blockcreatedate; // non-DB field int64_t minerreward; int64_t workinfoidstart; int64_t workinfoidend; @@ -2303,6 +2304,7 @@ extern double _blockhash_diff(char *hash, WHERE_FFL_ARGS); extern void dsp_blocks(K_ITEM *item, FILE *stream); extern cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx); +extern K_ITEM *find_blocks_new(K_ITEM *b_item, K_TREE_CTX *ctx); extern K_ITEM *find_prev_blocks(int32_t height); extern const char *blocks_confirmed(char *confirmed); extern void zero_on_new_block(); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 1e41f13a..ed5e9786 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -4997,6 +4997,11 @@ static char *cmd_mpayouts(__maybe_unused PGconn *conn, char *cmd, char *id, rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), + "block"CDTRF":%d=%ld%c", rows, + payouts->blockcreatedate.tv_sec, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + bigint_to_buf(payouts->elapsed, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "elapsed:%d=%s%c", @@ -5041,7 +5046,7 @@ static char *cmd_mpayouts(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c", rows, FLDSEP, - "payoutid,height,elapsed,amount,diffacc,minerreward,diffused,status", + "payoutid,height,block"CDTRF",elapsed,amount,diffacc,minerreward,diffused,status", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 71754783..7942a790 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -2621,6 +2621,33 @@ K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx) return find_in_ktree(blocks_root, &look, cmp_blocks, ctx); } +/* Find the matching NEW block - requires K_RLOCK() + * This requires calling find_blocks() first to get ctx */ +K_ITEM *find_blocks_new(K_ITEM *b_item, K_TREE_CTX *ctx) +{ + BLOCKS *blocks, *blocks2; + K_ITEM *b2_item; + + // Return what was passed in if it was NULL or was the NEW block + DATA_BLOCKS_NULL(blocks, b_item); + if (!b_item || blocks->confirmed[0] == BLOCKS_NEW) + return b_item; + + // NEW should be after the non-NEW block + b2_item = next_in_ktree(ctx); + DATA_BLOCKS_NULL(blocks2, b2_item); + while (b2_item && blocks2->height == blocks->height && + strcmp(blocks2->blockhash, blocks->blockhash) == 0) { + if (blocks2->confirmed[0] == BLOCKS_NEW) + return b2_item; + + b2_item = next_in_ktree(ctx); + DATA_BLOCKS_NULL(blocks2, b2_item); + } + + return NULL; +} + // Must be R or W locked before call K_ITEM *find_prev_blocks(int32_t height) { @@ -3314,22 +3341,9 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) goto oku; } DATA_BLOCKS(blocks, b_item); - b2_item = b_item; - DATA_BLOCKS(blocks2, b2_item); - while (b2_item && blocks2->height == height && - strcmp(blocks2->blockhash, blockhash) == 0) { - if (blocks2->confirmed[0] == BLOCKS_NEW) { - copy_tv(&end_tv, &(blocks2->createdate)); - if (!addr_cd) - addr_cd = &(blocks2->createdate); - break; - } - b2_item = next_in_ktree(b_ctx); - DATA_BLOCKS_NULL(blocks2, b2_item); - } + b2_item = find_blocks_new(b_item, b_ctx); K_RUNLOCK(blocks_free); - // If addr_cd was null it should've been set to the block NEW createdate - if (!addr_cd || end_tv.tv_sec == 0) { + if (!b2_item) { LOGEMERG("%s(): missing %s record for block %"PRId32 "/%"PRId64"/%s/%s/%"PRId64, __func__, blocks_confirmed(BLOCKS_NEW_STR), @@ -3338,6 +3352,10 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) blocks->reward); goto oku; } + DATA_BLOCKS(blocks2, b2_item); + copy_tv(&end_tv, &(blocks2->createdate)); + if (!addr_cd) + addr_cd = &(blocks2->createdate); LOGDEBUG("%s(): block %"PRId32"/%"PRId64"/%s/%s/%"PRId64, __func__, blocks->height, blocks->workinfoid, @@ -3639,6 +3657,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) bzero(payouts, sizeof(*payouts)); payouts->height = height; STRNCPY(payouts->blockhash, blockhash); + copy_tv(&(payouts->blockcreatedate), &(blocks2->createdate)); d64 = blocks->reward * 9 / 1000; g64 = blocks->reward - d64; payouts->minerreward = g64; @@ -3905,6 +3924,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) payouts2->payoutid = payouts->payoutid; payouts2->height = payouts->height; STRNCPY(payouts2->blockhash, payouts->blockhash); + copy_tv(&(payouts2->blockcreatedate), &(payouts->blockcreatedate)); payouts2->minerreward = payouts->minerreward; payouts2->workinfoidstart = payouts->workinfoidstart; payouts2->workinfoidend = payouts->workinfoidend; diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index d355be78..b4fd8eee 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -5501,8 +5501,10 @@ bool payouts_fill(PGconn *conn) { ExecStatusType rescode; PGresult *res; - K_ITEM *item; + K_ITEM *item, *b_item, *b2_item; + K_TREE_CTX ctx[1]; PAYOUTS *row; + BLOCKS *blocks; int n, i; char *field; char *sel; @@ -5616,6 +5618,29 @@ bool payouts_fill(PGconn *conn) if (!ok) break; + // This also of course, verifies the payouts -> blocks reference + b_item = find_blocks(row->height, row->blockhash, ctx); + if (!b_item) { + LOGERR("%s(): payoutid %"PRId64" references unknown " + "block %"PRId32"/%s", + __func__, row->payoutid, row->height, + row->blockhash); + ok = false; + break; + } else { + b2_item = find_blocks_new(b_item, ctx); + if (!b2_item) { + LOGERR("%s(): payoutid %"PRId64" references " + "block %"PRId32"/%s that has no NEW", + __func__, row->payoutid, row->height, + row->blockhash); + ok = false; + break; + } + DATA_BLOCKS(blocks, b2_item); + copy_tv(&(row->blockcreatedate), &(blocks->createdate)); + } + payouts_root = add_to_ktree(payouts_root, item, cmp_payouts); payouts_id_root = add_to_ktree(payouts_id_root, item, cmp_payouts_id); k_add_head(payouts_store, item); From 07f1a8d9d3b63b2cc8a659b91dbd485d4c26560d Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 30 Aug 2015 22:07:11 +1000 Subject: [PATCH 16/27] php - block stats are up to the last found block --- pool/base.php | 32 ++++++++++---------------------- pool/page_blocks.php | 6 ++++-- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/pool/base.php b/pool/base.php index 7c88113c..828454a3 100644 --- a/pool/base.php +++ b/pool/base.php @@ -34,39 +34,27 @@ function daysago($val) return ''; if ($val < 60) - $des = $val.'s'; + $des = number_format($val,0).'s'; else { - $val = round($val/6)/10; + $val = $val/60; if ($val < 60) - $des = $val.'min'; + $des = number_format($val,1).'min'; else { - $val = round($val/6)/10; + $val = $val/60; if ($val < 24) - { - $des = $val.'hr'; - if ($val != 1) - $des .= 's'; - } + $des = number_format($val,1).'hrs'; else { - $val = round($val/2.4)/10; - if ($val < 100) - { - $des = $val.'day'; - if ($val != 1) - $des .= 's'; - } + $val = $val/24; + if ($val < 43) + $des = number_format($val,1).'days'; else { - $val = round($val/0.7)/10; + $val = $val/7; if ($val < 10000) - { - $des = $val.'wk'; - if ($val != 1) - $des .= 's'; - } + $des = number_format($val,1).'wks'; else $des = ''; } diff --git a/pool/page_blocks.php b/pool/page_blocks.php index 167f2999..07a8b894 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -100,6 +100,8 @@ function doblocks($data, $user) $pg .= ""; $pg .= "\n"; + $since = $data['info']['lastblock']; + $count = $ans['s_rows']; for ($i = 0; $i < $count; $i++) { @@ -109,7 +111,7 @@ function doblocks($data, $user) $row = 'odd'; $desc = $ans['s_desc:'.$i]; - $age = daysago($ans['STAMP'] - $ans['s_createdate:'.$i]); + $age = daysago($since - $ans['s_createdate:'.$i]); $diff = number_format(100 * $ans['s_diffratio:'.$i], 2); $mean = number_format(100 * $ans['s_diffmean:'.$i], 2); @@ -122,7 +124,7 @@ function doblocks($data, $user) $pg .= ""; $pg .= ""; - $pg .= ""; + $pg .= ""; $pg .= ""; $pg .= ""; $pg .= ""; From a56fee239c888462729fffc7b98dd6f40736be7a Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 30 Aug 2015 22:09:27 +1000 Subject: [PATCH 17/27] php - remove leading zero from Block UTC day --- pool/page_mpayouts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pool/page_mpayouts.php b/pool/page_mpayouts.php index 60eec061..ca962854 100644 --- a/pool/page_mpayouts.php +++ b/pool/page_mpayouts.php @@ -37,7 +37,7 @@ function dompayouts($data, $user) $pg .= ""; $pg .= ''; - $pg .= ''; + $pg .= ''; $pg .= ''; $diffused = $ans['diffused:'.$i]; $pg .= ''; From 934ea3f07d6e48cb7a1764863f72a9779e184217 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 31 Aug 2015 23:04:43 +1000 Subject: [PATCH 18/27] php - block stats table age doesn't include the oldest block - use a date stamp instead --- pool/page_blocks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pool/page_blocks.php b/pool/page_blocks.php index 07a8b894..f7cc20ec 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -111,7 +111,7 @@ function doblocks($data, $user) $row = 'odd'; $desc = $ans['s_desc:'.$i]; - $age = daysago($since - $ans['s_createdate:'.$i]); + $age = gmdate('j/M H:i',$ans['s_createdate:'.$i]); $diff = number_format(100 * $ans['s_diffratio:'.$i], 2); $mean = number_format(100 * $ans['s_diffmean:'.$i], 2); From 369274b5215fbb5c5f8bd589a7eb3ad72e842bd7 Mon Sep 17 00:00:00 2001 From: kanoi Date: Wed, 2 Sep 2015 19:54:47 +1000 Subject: [PATCH 19/27] ckdb - calc 'rewards' for a new shift in case the payout has already been done --- src/ckdb.c | 3 +++ src/ckdb.h | 6 ++++- src/ckdb_cmd.c | 2 +- src/ckdb_data.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ckdb_dbio.c | 8 +++++++ 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 4cccaf8c..7f219aef 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -420,6 +420,7 @@ K_STORE *miningpayouts_store; // PAYOUTS K_TREE *payouts_root; K_TREE *payouts_id_root; +K_TREE *payouts_wid_root; K_LIST *payouts_free; K_STORE *payouts_store; cklock_t process_pplns_lock; @@ -1086,6 +1087,7 @@ static void alloc_storage() payouts_store = k_new_store(payouts_free); payouts_root = new_ktree(); payouts_id_root = new_ktree(); + payouts_wid_root = new_ktree(); auths_free = k_new_list("Auths", sizeof(AUTHS), ALLOC_AUTHS, LIMIT_AUTHS, true); @@ -1304,6 +1306,7 @@ static void dealloc_storage() FREE_ALL(poolstats); FREE_ALL(auths); + FREE_TREE(payouts_wid); FREE_TREE(payouts_id); FREE_TREE(payouts); FREE_STORE_DATA(payouts); diff --git a/src/ckdb.h b/src/ckdb.h index 8ab5cf26..6ae1bdd4 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.229" +#define CKDB_VERSION DB_VERSION"-1.230" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1600,6 +1600,7 @@ typedef struct payouts { extern K_TREE *payouts_root; extern K_TREE *payouts_id_root; +extern K_TREE *payouts_wid_root; extern K_LIST *payouts_free; extern K_STORE *payouts_store; extern cklock_t process_pplns_lock; @@ -2318,9 +2319,11 @@ extern K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, double diffacc); extern cmp_t cmp_payouts(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_payouts_id(K_ITEM *a, K_ITEM *b); +extern cmp_t cmp_payouts_wid(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_payouts(int32_t height, char *blockhash); extern K_ITEM *find_last_payouts(); extern K_ITEM *find_payoutid(int64_t payoutid); +extern K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx); extern double payout_stats(PAYOUTS *payouts, char *statname); extern bool process_pplns(int32_t height, char *blockhash, tv_t *now); extern cmp_t cmp_auths(K_ITEM *a, K_ITEM *b); @@ -2354,6 +2357,7 @@ extern bool workmarkers_generate(PGconn *conn, char *err, size_t siz, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root, bool none_error); extern bool reward_shifts(PAYOUTS *payouts, bool lock, int delta); +extern bool shift_rewards(K_ITEM *wm_item); extern cmp_t cmp_marks(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_marks(int64_t workinfoid); extern const char *marks_marktype(char *marktype); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index ed5e9786..11c9bac1 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -5541,7 +5541,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id, USEINFO(marks, 1, 1); USEINFO(blocks, 1, 1); USEINFO(miningpayouts, 1, 1); - USEINFO(payouts, 1, 2); + USEINFO(payouts, 1, 3); USEINFO(auths, 1, 1); USEINFO(poolstats, 1, 1); USEINFO(userstats, 2, 1); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 7942a790..0700f727 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -3141,6 +3141,22 @@ cmp_t cmp_payouts_id(K_ITEM *a, K_ITEM *b) return c; } +/* order by workinfoidend asc,expirydate asc + * This must use workinfoidend, not workinfoidstart, since a change + * in the payout PPLNS N could have 2 payouts with the same start, + * but currently there is only one payout per block + * i.e. workinfoidend can only have one payout */ +cmp_t cmp_payouts_wid(K_ITEM *a, K_ITEM *b) +{ + PAYOUTS *pa, *pb; + DATA_PAYOUTS(pa, a); + DATA_PAYOUTS(pb, b); + cmp_t c = CMP_BIGINT(pa->workinfoidend, pb->workinfoidend); + if (c == 0) + c = CMP_TV(pa->expirydate, pb->expirydate); + return c; +} + K_ITEM *find_payouts(int32_t height, char *blockhash) { PAYOUTS payouts; @@ -3189,6 +3205,25 @@ K_ITEM *find_payoutid(int64_t payoutid) return find_in_ktree(payouts_id_root, &look, cmp_payouts_id, ctx); } +// First payouts workinfoidend equal or before workinfoidend +K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx) +{ + PAYOUTS payouts; + K_TREE_CTX ctx0[1]; + K_ITEM look; + + if (ctx == NULL) + ctx = ctx0; + + payouts.workinfoidend = workinfoidend+1; + payouts.expirydate.tv_sec = 0; + payouts.expirydate.tv_usec = 0; + + INIT_PAYOUTS(&look); + look.data = (void *)(&payouts); + return find_before_in_ktree(payouts_wid_root, &look, cmp_payouts_wid, ctx); +} + /* Values from payout stats, returns -1 if statname isn't found * If code needs a value then it probably really should be a new payouts field * rather than stored in the stats passed to the pplns2 web page @@ -4635,6 +4670,35 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta) return did_one; } +// (re)calculate rewards for a shift +bool shift_rewards(K_ITEM *wm_item) +{ + PAYOUTS *payouts = NULL; + K_TREE_CTX ctx[1]; + WORKMARKERS *wm; + K_ITEM *p_item; + int rewards = 0; + + DATA_WORKMARKERS(wm, wm_item); + + // Deadlock risk since calling code should have workmarkers locked + K_WLOCK(payouts_free); + p_item = find_payouts_wid(wm->workinfoidend, ctx); + DATA_PAYOUTS_NULL(payouts, p_item); + // a workmarker should not cross a payout boundary + while (p_item && payouts->workinfoidstart <= wm->workinfoidstart && + wm->workinfoidend <= payouts->workinfoidend) { + if (CURRENT(&(payouts->expirydate))) + rewards++; + p_item = prev_in_ktree(ctx); + DATA_PAYOUTS_NULL(payouts, p_item); + } + K_WUNLOCK(payouts_free); + + wm->rewards = rewards; + return (rewards > 0); +} + // order by expirydate asc,workinfoid asc // TODO: add poolinstance cmp_t cmp_marks(K_ITEM *a, K_ITEM *b) diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index b4fd8eee..e6552ed2 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -5119,12 +5119,15 @@ void payouts_add_ram(bool ok, K_ITEM *p_item, K_ITEM *old_p_item, tv_t *cd) DATA_PAYOUTS(oldp, old_p_item); payouts_root = remove_from_ktree(payouts_root, old_p_item, cmp_payouts); payouts_id_root = remove_from_ktree(payouts_id_root, old_p_item, cmp_payouts_id); + payouts_wid_root = remove_from_ktree(payouts_wid_root, old_p_item, cmp_payouts_wid); copy_tv(&(oldp->expirydate), cd); payouts_root = add_to_ktree(payouts_root, old_p_item, cmp_payouts); payouts_id_root = add_to_ktree(payouts_id_root, old_p_item, cmp_payouts_id); + payouts_wid_root = add_to_ktree(payouts_wid_root, old_p_item, cmp_payouts_wid); } payouts_root = add_to_ktree(payouts_root, p_item, cmp_payouts); payouts_id_root = add_to_ktree(payouts_id_root, p_item, cmp_payouts_id); + payouts_wid_root = add_to_ktree(payouts_wid_root, p_item, cmp_payouts_wid); k_add_head(payouts_store, p_item); } K_WUNLOCK(payouts_free); @@ -5431,9 +5434,11 @@ K_ITEM *payouts_full_expire(PGconn *conn, int64_t payoutid, tv_t *now, bool lock DATA_PAYOUTS(payouts, po_item); payouts_root = remove_from_ktree(payouts_root, po_item, cmp_payouts); payouts_id_root = remove_from_ktree(payouts_id_root, po_item, cmp_payouts_id); + payouts_wid_root = remove_from_ktree(payouts_wid_root, po_item, cmp_payouts_wid); copy_tv(&(payouts->expirydate), now); payouts_root = add_to_ktree(payouts_root, po_item, cmp_payouts); payouts_id_root = add_to_ktree(payouts_id_root, po_item, cmp_payouts_id); + payouts_wid_root = add_to_ktree(payouts_wid_root, po_item, cmp_payouts_wid); mp_item = first_miningpayouts(payoutid, mp_ctx); DATA_MININGPAYOUTS_NULL(mp, mp_item); @@ -5643,6 +5648,7 @@ bool payouts_fill(PGconn *conn) payouts_root = add_to_ktree(payouts_root, item, cmp_payouts); payouts_id_root = add_to_ktree(payouts_id_root, item, cmp_payouts_id); + payouts_wid_root = add_to_ktree(payouts_wid_root, item, cmp_payouts_wid); k_add_head(payouts_store, item); if (CURRENT(&(row->expirydate)) && PAYGENERATED(row->status)) @@ -6726,6 +6732,8 @@ unparam: cmp_workmarkers_workinfoid); } if (wm_item) { + shift_rewards(wm_item); + workmarkers_root = add_to_ktree(workmarkers_root, wm_item, cmp_workmarkers); From 20d53cad15e1fd40df2ac4a8c9d35a7956ba19dc Mon Sep 17 00:00:00 2001 From: kanoi Date: Wed, 2 Sep 2015 23:15:58 +1000 Subject: [PATCH 20/27] ckdb - demote shift_rewards payouts lock to read - no payout data is changed --- src/ckdb.h | 2 +- src/ckdb_data.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 6ae1bdd4..70f9df1f 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.230" +#define CKDB_VERSION DB_VERSION"-1.231" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_data.c b/src/ckdb_data.c index 0700f727..fd8ca978 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -4682,7 +4682,7 @@ bool shift_rewards(K_ITEM *wm_item) DATA_WORKMARKERS(wm, wm_item); // Deadlock risk since calling code should have workmarkers locked - K_WLOCK(payouts_free); + K_RLOCK(payouts_free); p_item = find_payouts_wid(wm->workinfoidend, ctx); DATA_PAYOUTS_NULL(payouts, p_item); // a workmarker should not cross a payout boundary @@ -4693,7 +4693,7 @@ bool shift_rewards(K_ITEM *wm_item) p_item = prev_in_ktree(ctx); DATA_PAYOUTS_NULL(payouts, p_item); } - K_WUNLOCK(payouts_free); + K_RUNLOCK(payouts_free); wm->rewards = rewards; return (rewards > 0); From 5598bc9dbd7dc002d82bd5037108f359a28f8bb7 Mon Sep 17 00:00:00 2001 From: kanoi Date: Thu, 3 Sep 2015 11:09:59 +1000 Subject: [PATCH 21/27] README - add missing ckdb build dependencies --- README | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README b/README index c701deb0..edf3c134 100644 --- a/README +++ b/README @@ -80,12 +80,15 @@ sudo apt-get install build-essential make -Building with ckdb requires installation of the postgresql development library. +Building with ckdb requires installation of the postgresql, gsl and ssl +development libraries. -sudo apt-get install build-essential libpq-dev +sudo apt-get install build-essential libpq-dev libgsl0ldbl libgsl0-dev ./configure make +N.B. ckdb also requires libssl-dev but libpq-dev depends on it and installs it + Building from git also requires autoconf and automake From 4c243f24ccdd32f995f82066833862c392b2e6e1 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 5 Sep 2015 01:38:15 +1000 Subject: [PATCH 22/27] ckdb/php - store, and use, the block and prevous valid block createtime in BLOCKS --- pool/page_blocks.php | 2 +- src/ckdb.c | 11 +- src/ckdb.h | 23 ++-- src/ckdb_cmd.c | 78 ++++++------ src/ckdb_data.c | 282 +++++++++++++++++++++++++++++++------------ src/ckdb_dbio.c | 106 +++++++++++----- 6 files changed, 340 insertions(+), 162 deletions(-) diff --git a/pool/page_blocks.php b/pool/page_blocks.php index f7cc20ec..73df3c55 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -111,7 +111,7 @@ function doblocks($data, $user) $row = 'odd'; $desc = $ans['s_desc:'.$i]; - $age = gmdate('j/M H:i',$ans['s_createdate:'.$i]); + $age = daysago($since - $ans['s_prevcreatedate:'.$i]); $diff = number_format(100 * $ans['s_diffratio:'.$i], 2); $mean = number_format(100 * $ans['s_diffmean:'.$i], 2); diff --git a/src/ckdb.c b/src/ckdb.c index 7f219aef..935c8aa6 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1483,8 +1483,7 @@ static bool setup_data() if (workinfo_current) { DATA_WORKINFO(wic, workinfo_current); STRNCPY(wi.coinbase1, wic->coinbase1); - wi.createdate.tv_sec = 0L; - wi.createdate.tv_usec = 0L; + DATE_ZERO(&(wi.createdate)); INIT_WORKINFO(&look); look.data = (void *)(&wi); // Find the first workinfo for this height @@ -1524,7 +1523,7 @@ static bool setup_data() (_seqset)->seqdata[_i].firsttime.tv_sec = \ (_seqset)->seqdata[_i].firsttime.tv_usec = \ (_seqset)->seqdata[_i].lasttime.tv_sec = \ - (_seqset)->seqdata[_i].lasttime.tv_usec = 0; \ + (_seqset)->seqdata[_i].lasttime.tv_usec = 0L; \ } \ } while (0); @@ -2902,7 +2901,7 @@ static void summarise_blocks() K_RUNLOCK(blocks_free); if (!b_prev) { wi_start = 0; - elapsed_start.tv_sec = elapsed_start.tv_usec = 0L; + DATE_ZERO(&elapsed_start); prev_hi = 0; } else { DATA_BLOCKS(prev_blocks, b_prev); @@ -2921,7 +2920,7 @@ static void summarise_blocks() copy_tv(&elapsed_start, &(prev_workinfo->createdate)); prev_hi = prev_blocks->height; } - elapsed_finish.tv_sec = elapsed_finish.tv_usec = 0L; + DATE_ZERO(&elapsed_finish); // Add up the sharesummaries, abort if any SUMMARY_NEW looksharesummary.workinfoid = wi_finish; @@ -5121,7 +5120,7 @@ static void confirm_reload() } } else { if (confirm_first_workinfoid == 0) { - start.tv_sec = start.tv_usec = 0; + DATE_ZERO(&start); LOGWARNING("%s() no start workinfo found ... " "using time 0", __func__); } else { diff --git a/src/ckdb.h b/src/ckdb.h index 70f9df1f..e98cf5ef 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.231" +#define CKDB_VERSION DB_VERSION"-1.232" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -270,6 +270,8 @@ extern const tv_t date_eot; #define DATE_BEGIN 1388620800L extern const tv_t date_begin; +#define DATE_ZERO(_tv) (_tv)->tv_sec = (_tv)->tv_usec = 0L + #define BTC_TO_D(_amt) ((double)((_amt) / 100000000.0)) // argv -y - don't run in ckdb mode, just confirm sharesummaries @@ -592,8 +594,7 @@ enum cmd_values { STRNCPY(_row->createby, _by); \ STRNCPY(_row->createcode, _code); \ STRNCPY(_row->createinet, _inet); \ - _row->modifydate.tv_sec = 0; \ - _row->modifydate.tv_usec = 0; \ + DATE_ZERO(&(_row->modifydate)); \ _row->modifyby[0] = '\0'; \ _row->modifycode[0] = '\0'; \ _row->modifyinet[0] = '\0'; \ @@ -615,8 +616,7 @@ enum cmd_values { SET_CREATEBY(_list, _row->createby, _by); \ SET_CREATECODE(_list, _row->createcode, _code); \ SET_CREATEINET(_list, _row->createinet, _inet); \ - _row->modifydate.tv_sec = 0; \ - _row->modifydate.tv_usec = 0; \ + DATE_ZERO(&(_row->modifydate)); \ SET_MODIFYBY(_list, _row->modifyby, EMPTY); \ SET_MODIFYCODE(_list, _row->modifycode, EMPTY); \ SET_MODIFYINET(_list, _row->modifyinet, EMPTY); \ @@ -1496,6 +1496,10 @@ typedef struct blocks { double diffmean; double cdferl; double luck; + + // To save looking them up when needed + tv_t prevcreatedate; // non-DB field + tv_t blockcreatedate; // non-DB field } BLOCKS; #define ALLOC_BLOCKS 100 @@ -2305,12 +2309,15 @@ extern double _blockhash_diff(char *hash, WHERE_FFL_ARGS); extern void dsp_blocks(K_ITEM *item, FILE *stream); extern cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx); -extern K_ITEM *find_blocks_new(K_ITEM *b_item, K_TREE_CTX *ctx); extern K_ITEM *find_prev_blocks(int32_t height); extern const char *blocks_confirmed(char *confirmed); extern void zero_on_new_block(); extern void set_block_share_counters(); extern bool check_update_blocks_stats(tv_t *stats); +#define set_blockcreatedate(_h) _set_blockcreatedate(_h, WHERE_FFL_HERE) +extern bool _set_blockcreatedate(int32_t oldest_height, WHERE_FFL_ARGS); +#define set_prevcreatedate(_h) _set_prevcreatedate(_h, WHERE_FFL_HERE) +extern bool _set_prevcreatedate(int32_t oldest_height, WHERE_FFL_ARGS); extern cmp_t cmp_miningpayouts(K_ITEM *a, K_ITEM *b); extern K_ITEM *find_miningpayouts(int64_t payoutid, int64_t userid); extern K_ITEM *first_miningpayouts(int64_t payoutid, K_TREE_CTX *ctx); @@ -2376,8 +2383,8 @@ extern K_ITEM *_find_create_userinfo(int64_t userid, bool lock, WHERE_FFL_ARGS); #define userinfo_update(_s, _ss, _ms) _userinfo_update(_s, _ss, _ms, true, true) extern void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary, MARKERSUMMARY *markersummary, bool ss_sub, bool lock); -#define userinfo_block(_blocks, _isnew) _userinfo_block(_blocks, _isnew, true) -extern void _userinfo_block(BLOCKS *blocks, enum info_type isnew, bool lock); +#define userinfo_block(_blocks, _isnew, _delta) _userinfo_block(_blocks, _isnew, _delta, true) +extern void _userinfo_block(BLOCKS *blocks, enum info_type isnew, int delta, bool lock); // *** // *** PostgreSQL functions ckdb_dbio.c diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 11c9bac1..f724b218 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -1128,8 +1128,7 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, char tmp[1024]; char *buf, *desc, desc_buf[64]; size_t len, off; - int32_t height = -1; - tv_t first_cd = {0,0}, stats_tv = {0,0}, stats_tv2 = {0,0}; + tv_t stats_tv = {0,0}, stats_tv2 = {0,0}; int rows, srows, tot, seq; int64_t maxrows; bool has_stats; @@ -1164,13 +1163,6 @@ redo: b_item = last_in_ktree(blocks_root, ctx); while (b_item && rows < (int)maxrows) { DATA_BLOCKS(blocks, b_item); - /* For each block remember the initial createdate - * Reverse sort order the oldest expirydate is first - * which should be the 'n' record */ - if (height != blocks->height) { - height = blocks->height; - copy_tv(&first_cd, &(blocks->createdate)); - } if (CURRENT(&(blocks->expirydate))) { if (blocks->confirmed[0] == BLOCKS_ORPHAN || blocks->confirmed[0] == BLOCKS_REJECT) { @@ -1207,16 +1199,24 @@ redo: snprintf(tmp, sizeof(tmp), "workername:%d=%s%c", rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + // When block was found snprintf(tmp, sizeof(tmp), "first"CDTRF":%d=%ld%c", rows, - first_cd.tv_sec, FLDSEP); + blocks->blockcreatedate.tv_sec, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + // Last time block was updated snprintf(tmp, sizeof(tmp), CDTRF":%d=%ld%c", rows, blocks->createdate.tv_sec, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + // When previous valid block was found + snprintf(tmp, sizeof(tmp), + "prev"CDTRF":%d=%ld%c", rows, + blocks->prevcreatedate.tv_sec, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "confirmed:%d=%s%cstatus:%d=%s%c", rows, blocks->confirmed, FLDSEP, rows, @@ -1305,6 +1305,7 @@ redo: "s_desc:%d=%s%c" "s_height:%d=%d%c" "s_"CDTRF":%d=%ld%c" + "s_prev"CDTRF":%d=%ld%c" "s_diffratio:%d=%.8f%c" "s_diffmean:%d=%.8f%c" "s_cdferl:%d=%.8f%c" @@ -1312,7 +1313,8 @@ redo: srows, seq, FLDSEP, srows, desc, FLDSEP, srows, (int)(blocks->height), FLDSEP, - srows, blocks->createdate.tv_sec, FLDSEP, + srows, blocks->blockcreatedate.tv_sec, FLDSEP, + srows, blocks->prevcreatedate.tv_sec, FLDSEP, srows, blocks->diffratio, FLDSEP, srows, blocks->diffmean, FLDSEP, srows, blocks->cdferl, FLDSEP, @@ -1344,8 +1346,8 @@ redo: snprintf(tmp, sizeof(tmp), "s_rows=%d%cs_flds=%s%c", srows, FLDSEP, - "s_seq,s_desc,s_height,s_"CDTRF",s_diffratio,s_diffmean," - "s_cdferl,s_luck", + "s_seq,s_desc,s_height,s_"CDTRF",s_prev"CDTRF",s_diffratio," + "s_diffmean,s_cdferl,s_luck", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); @@ -1353,8 +1355,8 @@ redo: "rows=%d%cflds=%s%c", rows, FLDSEP, "seq,height,blockhash,nonce,reward,workername,first"CDTRF"," - CDTRF",confirmed,status,info,statsconf,diffacc,diffinv," - "shareacc,shareinv,elapsed,netdiff,diffratio,cdf,luck", + CDTRF",prev"CDTRF",confirmed,status,info,statsconf,diffacc," + "diffinv,shareacc,shareinv,elapsed,netdiff,diffratio,cdf,luck", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); @@ -1706,8 +1708,7 @@ static char *cmd_percent(char *cmd, char *id, tv_t *now, USERS *users) // Add up all user's worker stats to be divided into payout percentages lookworkers.userid = users->userid; lookworkers.workername[0] = '\0'; - lookworkers.expirydate.tv_sec = 0; - lookworkers.expirydate.tv_usec = 0; + DATE_ZERO(&(lookworkers.expirydate)); w_look.data = (void *)(&lookworkers); w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx); DATA_WORKERS_NULL(workers, w_item); @@ -1968,8 +1969,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, lookworkers.userid = users->userid; lookworkers.workername[0] = '\0'; - lookworkers.expirydate.tv_sec = 0; - lookworkers.expirydate.tv_usec = 0; + DATE_ZERO(&(lookworkers.expirydate)); w_look.data = (void *)(&lookworkers); w_item = find_after_in_ktree(workers_root, &w_look, cmp_workers, w_ctx); DATA_WORKERS_NULL(workers, w_item); @@ -1983,7 +1983,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, copy_tv(&last_share, &(workerstatus->last_share)); K_RUNLOCK(workerstatus_free); } else - last_share.tv_sec = last_share.tv_usec = 0L; + DATE_ZERO(&last_share); if (tvdiff(now, &last_share) < oldworkers) { str_to_buf(workers->workername, reply, sizeof(reply)); @@ -2021,7 +2021,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, w_elapsed = -1; if (!ws_item) { - w_lastshare.tv_sec = 0; + w_lastshare.tv_sec = 0L; w_lastdiff = w_diffacc = w_diffinv = w_diffsta = w_diffdup = w_diffhi = @@ -2029,7 +2029,7 @@ static char *cmd_workers(__maybe_unused PGconn *conn, char *cmd, char *id, w_shareinv = w_sharesta = w_sharedup = w_sharehi = w_sharerej = w_active_diffacc = 0; - w_active_start.tv_sec = 0; + w_active_start.tv_sec = 0L; } else { DATA_WORKERSTATUS(workerstatus, ws_item); // It's bad to read possibly changing data @@ -4018,8 +4018,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, LOGDEBUG("%s(): height %"PRId32, __func__, height); - block_tv.tv_sec = block_tv.tv_usec = 0L; - cd.tv_sec = cd.tv_usec = 0L; + DATE_ZERO(&block_tv); + DATE_ZERO(&cd); lookblocks.height = height + 1; lookblocks.blockhash[0] = '\0'; INIT_BLOCKS(&b_look); @@ -4446,7 +4446,6 @@ static char *cmd_pplns2(__maybe_unused PGconn *conn, char *cmd, char *id, PAYMENTS *payments; PAYOUTS *payouts; BLOCKS lookblocks, *blocks; - tv_t block_tv = { 0L, 0L }; WORKINFO *bworkinfo, *workinfo; char ndiffbin[TXT_SML+1]; double ndiff; @@ -4470,36 +4469,26 @@ static char *cmd_pplns2(__maybe_unused PGconn *conn, char *cmd, char *id, LOGDEBUG("%s(): height %"PRId32, __func__, height); - lookblocks.height = height + 1; + lookblocks.height = height; lookblocks.blockhash[0] = '\0'; INIT_BLOCKS(&b_look); b_look.data = (void *)(&lookblocks); K_RLOCK(blocks_free); - b_item = find_before_in_ktree(blocks_root, &b_look, cmp_blocks, b_ctx); + b_item = find_after_in_ktree(blocks_root, &b_look, cmp_blocks, b_ctx); + K_RUNLOCK(blocks_free); if (!b_item) { K_RUNLOCK(blocks_free); - snprintf(reply, siz, "ERR.no block height %"PRId32, height); + snprintf(reply, siz, "ERR.no block height >= %"PRId32, height); return strdup(reply); } DATA_BLOCKS(blocks, b_item); - while (b_item && blocks->height == height) { - if (blocks->confirmed[0] == BLOCKS_NEW) - copy_tv(&block_tv, &(blocks->createdate)); - // Allow any state, but report it - if (CURRENT(&(blocks->expirydate))) - break; - b_item = prev_in_ktree(b_ctx); - DATA_BLOCKS_NULL(blocks, b_item); - } - K_RUNLOCK(blocks_free); if (!b_item || blocks->height != height) { snprintf(reply, siz, "ERR.no block height %"PRId32, height); return strdup(reply); } - if (block_tv.tv_sec == 0) { - snprintf(reply, siz, "ERR.block %"PRId32" missing '%s' record", - height, - blocks_confirmed(BLOCKS_NEW_STR)); + if (blocks->blockcreatedate.tv_sec == 0) { + snprintf(reply, siz, "ERR.block %"PRId32" has 0 blockcreatedate", + height); return strdup(reply); } if (!CURRENT(&(blocks->expirydate))) { @@ -4676,10 +4665,11 @@ static char *cmd_pplns2(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "begin_epoch=%ld%c", workinfo->createdate.tv_sec, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - tv_to_buf(&block_tv, tv_buf, sizeof(tv_buf)); + tv_to_buf(&(blocks->blockcreatedate), tv_buf, sizeof(tv_buf)); snprintf(tmp, sizeof(tmp), "block_stamp=%s%c", tv_buf, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); - snprintf(tmp, sizeof(tmp), "block_epoch=%ld%c", block_tv.tv_sec, FLDSEP); + snprintf(tmp, sizeof(tmp), "block_epoch=%ld%c", + blocks->blockcreatedate.tv_sec, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); tv_to_buf(&(payouts->lastshareacc), tv_buf, sizeof(tv_buf)); snprintf(tmp, sizeof(tmp), "end_stamp=%s%c", tv_buf, FLDSEP); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index fd8ca978..63a872c0 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -369,8 +369,7 @@ void _txt_to_data(enum data_type typ, char *nam, char *fld, void *data, size_t s long sec, nsec; int c; // Caller test for tv_sec=0 for failure - ((tv_t *)data)->tv_sec = 0L; - ((tv_t *)data)->tv_usec = 0L; + DATE_ZERO((tv_t *)data); c = sscanf(fld, "%ld,%ld", &sec, &nsec); if (c > 0) { ((tv_t *)data)->tv_sec = (time_t)sec; @@ -1474,8 +1473,7 @@ K_ITEM *first_workers(int64_t userid, K_TREE_CTX *ctx) workers.userid = userid; workers.workername[0] = '\0'; - workers.expirydate.tv_sec = 0L; - workers.expirydate.tv_usec = 0L; + DATE_ZERO(&(workers.expirydate)); INIT_WORKERS(&look); look.data = (void *)(&workers); @@ -1628,8 +1626,7 @@ K_ITEM *find_paymentaddresses_create(int64_t userid, K_TREE_CTX *ctx) K_ITEM look, *item; paymentaddresses.userid = userid; - paymentaddresses.createdate.tv_sec = 0; - paymentaddresses.createdate.tv_usec = 0; + DATE_ZERO(&(paymentaddresses.createdate)); paymentaddresses.payaddress[0] = '\0'; INIT_PAYMENTADDRESSES(&look); @@ -1849,8 +1846,7 @@ K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height) * activationdate will all be the default value and not * decide the outcome */ STRNCPY(optioncontrol.optionname, optionname); - optioncontrol.activationdate.tv_sec = 0L; - optioncontrol.activationdate.tv_usec = 0L; + DATE_ZERO(&(optioncontrol.activationdate)); optioncontrol.activationheight = OPTIONCONTROL_HEIGHT - 1; optioncontrol.expirydate.tv_sec = default_expiry.tv_sec; optioncontrol.expirydate.tv_usec = default_expiry.tv_usec; @@ -2045,8 +2041,8 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code, LOGDEBUG("%s(): age", __func__); - ss_first->tv_sec = ss_first->tv_usec = - ss_last->tv_sec = ss_last->tv_usec = 0; + DATE_ZERO(ss_first); + DATE_ZERO(ss_last); *ss_count = *s_count = *s_diff = 0; wi_item = find_workinfo(workinfoid, NULL); @@ -2142,8 +2138,7 @@ bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by, char *code, lookshares.workinfoid = workinfoid; lookshares.userid = sharesummary->userid; strcpy(lookshares.workername, sharesummary->workername); - lookshares.createdate.tv_sec = 0; - lookshares.createdate.tv_usec = 0; + DATE_ZERO(&(lookshares.createdate)); s_look.data = (void *)(&lookshares); K_WLOCK(shares_free); @@ -2390,8 +2385,8 @@ void auto_age_older(int64_t workinfoid, char *poolinstance, char *by, cmp_sharesummary_workinfoid, ctx); DATA_SHARESUMMARY_NULL(sharesummary, ss_item); - ss_first_min.tv_sec = ss_first_min.tv_usec = - ss_last_max.tv_sec = ss_last_max.tv_usec = 0; + DATE_ZERO(&ss_first_min); + DATE_ZERO(&ss_last_max); ss_count_tot = s_count_tot = s_diff_tot = 0; found = false; @@ -2621,33 +2616,6 @@ K_ITEM *find_blocks(int32_t height, char *blockhash, K_TREE_CTX *ctx) return find_in_ktree(blocks_root, &look, cmp_blocks, ctx); } -/* Find the matching NEW block - requires K_RLOCK() - * This requires calling find_blocks() first to get ctx */ -K_ITEM *find_blocks_new(K_ITEM *b_item, K_TREE_CTX *ctx) -{ - BLOCKS *blocks, *blocks2; - K_ITEM *b2_item; - - // Return what was passed in if it was NULL or was the NEW block - DATA_BLOCKS_NULL(blocks, b_item); - if (!b_item || blocks->confirmed[0] == BLOCKS_NEW) - return b_item; - - // NEW should be after the non-NEW block - b2_item = next_in_ktree(ctx); - DATA_BLOCKS_NULL(blocks2, b2_item); - while (b2_item && blocks2->height == blocks->height && - strcmp(blocks2->blockhash, blocks->blockhash) == 0) { - if (blocks2->confirmed[0] == BLOCKS_NEW) - return b2_item; - - b2_item = next_in_ktree(ctx); - DATA_BLOCKS_NULL(blocks2, b2_item); - } - - return NULL; -} - // Must be R or W locked before call K_ITEM *find_prev_blocks(int32_t height) { @@ -2660,8 +2628,7 @@ K_ITEM *find_prev_blocks(int32_t height) * not NEW, blocks, which might not find the right one */ lookblocks.height = height; lookblocks.blockhash[0] = '\0'; - lookblocks.expirydate.tv_sec = 0L; - lookblocks.expirydate.tv_usec = 0L; + DATE_ZERO(&(lookblocks.expirydate)); INIT_BLOCKS(&look); look.data = (void *)(&lookblocks); @@ -3020,6 +2987,184 @@ bool check_update_blocks_stats(tv_t *stats) return true; } +// Must be under K_WLOCK(blocks_free) when called except during DB load +bool _set_blockcreatedate(int32_t oldest_height, WHERE_FFL_ARGS) +{ + K_TREE_CTX ctx[1]; + BLOCKS *blocks; + K_ITEM *b_item; + int32_t height; + char blockhash[TXT_BIG+1]; + char cd_buf[DATE_BUFSIZ]; + tv_t createdate; + bool ok = true; + + // No blocks? + if (blocks_store->count == 0) + return true; + + height = 0; + blockhash[0] = '\0'; + DATE_ZERO(&createdate); + b_item = last_in_ktree(blocks_root, ctx); + DATA_BLOCKS_NULL(blocks, b_item); + while (b_item && blocks->height >= oldest_height) { + // NEW will be first going back + if (blocks->confirmed[0] == BLOCKS_NEW) { + height = blocks->height; + STRNCPY(blockhash, blocks->blockhash); + copy_tv(&createdate, &(blocks->createdate)); + } + if (blocks->height != height || + strcmp(blocks->blockhash, blockhash) != 0) { + // Missing NEW + tv_to_buf(&(blocks->expirydate), cd_buf, sizeof(cd_buf)); + LOGEMERG("%s() block %"PRId32"/%s/%s/%s has no '" + BLOCKS_NEW_STR "' prev was %"PRId32"/%s." + WHERE_FFL, + __func__, + blocks->height, blocks->blockhash, + blocks->confirmed, cd_buf, + height, blockhash, WHERE_FFL_PASS); + ok = false; + + height = blocks->height; + STRNCPY(blockhash, blocks->blockhash); + // set a useable (incorrect) value + copy_tv(&createdate, &(blocks->createdate)); + } + // Always update it + copy_tv(&(blocks->blockcreatedate), &createdate); + + b_item = prev_in_ktree(ctx); + DATA_BLOCKS_NULL(blocks, b_item); + } + return ok; +} + +// Must be under K_WLOCK(blocks_free) when called except during DB load +bool _set_prevcreatedate(int32_t oldest_height, WHERE_FFL_ARGS) +{ + K_ITEM look, *b_item = NULL, *wi_item; + BLOCKS lookblocks, *blocks = NULL; + K_TREE_CTX b_ctx[1], wi_ctx[1]; + WORKINFO *workinfo; + char curr_blockhash[TXT_BIG+1]; + char cd_buf[DATE_BUFSIZ]; + int32_t curr_height; + tv_t prev_createdate; + tv_t curr_createdate; + bool ok = true, currok = false; + + // No blocks? + if (blocks_store->count == 0) + return true; + + // Find first 'ok' block before oldest_height + lookblocks.height = oldest_height; + lookblocks.blockhash[0] = '\0'; + DATE_ZERO(&(lookblocks.expirydate)); + + INIT_BLOCKS(&look); + look.data = (void *)(&lookblocks); + b_item = find_before_in_ktree(blocks_root, &look, cmp_blocks, b_ctx); + while (b_item) { + DATA_BLOCKS(blocks, b_item); + if (CURRENT(&(blocks->expirydate)) && + blocks->confirmed[0] != BLOCKS_ORPHAN && + blocks->confirmed[0] != BLOCKS_REJECT) + break; + b_item = prev_in_ktree(b_ctx); + } + + // Setup prev_createdate + if (b_item) { + /* prev_createdate is the ok b_item (before oldest_height) + * _set_blockcreatedate() should always be called + * before calling _set_prevcreatedate() */ + copy_tv(&prev_createdate, &(blocks->blockcreatedate)); + + /* Move b_item forward to the next block + * since we don't have the prev value for b_item and + * also don't need to update the b_item block */ + curr_height = blocks->height; + STRNCPY(curr_blockhash, blocks->blockhash); + while (b_item && blocks->height == curr_height && + strcmp(blocks->blockhash, curr_blockhash) == 0) { + b_item = next_in_ktree(b_ctx); + DATA_BLOCKS_NULL(blocks, b_item); + } + } else { + /* There's none before oldest_height, so instead use: + * 'Pool Start' = first workinfo createdate */ + K_RLOCK(workinfo_free); + wi_item = first_in_ktree(workinfo_root, wi_ctx); + K_RUNLOCK(workinfo_free); + if (wi_item) { + DATA_WORKINFO(workinfo, wi_item); + copy_tv(&prev_createdate, &(workinfo->createdate)); + } else { + /* Shouldn't be possible since this function is first + * called after workinfo is loaded and the workinfo + * for each block must exist - thus data corruption */ + DATE_ZERO(&prev_createdate); + LOGEMERG("%s() DB/tree corruption - blocks exist but " + "no workinfo exist!" + WHERE_FFL, + __func__, WHERE_FFL_PASS); + ok = false; + } + b_item = first_in_ktree(blocks_root, b_ctx); + } + + // curr_* is unset and will be set first time in the while loop + curr_height = 0; + curr_blockhash[0] = '\0'; + DATE_ZERO(&curr_createdate); + currok = false; + while (b_item) { + DATA_BLOCKS(blocks, b_item); + // While the same block, keep setting it + if (blocks->height == curr_height && + strcmp(blocks->blockhash, curr_blockhash) == 0) { + copy_tv(&(blocks->prevcreatedate), &prev_createdate); + } else { + // Next block - if currok then 'prev' becomes 'curr' + if (currok) + copy_tv(&prev_createdate, &curr_createdate); + + // New curr - CURRENT will be first + if (!CURRENT(&(blocks->expirydate))) { + tv_to_buf(&(blocks->expirydate), cd_buf, + sizeof(cd_buf)); + LOGEMERG("%s() block %"PRId32"/%s/%s/%s first " + "record is not CURRENT" WHERE_FFL, + __func__, + blocks->height, blocks->blockhash, + blocks->confirmed, cd_buf, + WHERE_FFL_PASS); + ok = false; + } + + curr_height = blocks->height; + STRNCPY(curr_blockhash, blocks->blockhash); + copy_tv(&curr_createdate, &(blocks->blockcreatedate)); + + if (CURRENT(&(blocks->expirydate)) && + blocks->confirmed[0] != BLOCKS_ORPHAN && + blocks->confirmed[0] != BLOCKS_REJECT) + currok = true; + else + currok = false; + + // Set it + copy_tv(&(blocks->prevcreatedate), &prev_createdate); + } + b_item = next_in_ktree(b_ctx); + } + return ok; +} + /* order by payoutid asc,userid asc,expirydate asc * i.e. only one payout amount per block per user */ cmp_t cmp_miningpayouts(K_ITEM *a, K_ITEM *b) @@ -3063,8 +3208,7 @@ K_ITEM *first_miningpayouts(int64_t payoutid, K_TREE_CTX *ctx) miningpayouts.payoutid = payoutid; miningpayouts.userid = 0; - miningpayouts.expirydate.tv_sec = 0; - miningpayouts.expirydate.tv_usec = 0; + DATE_ZERO(&(miningpayouts.expirydate)); INIT_MININGPAYOUTS(&look); look.data = (void *)(&miningpayouts); @@ -3216,8 +3360,7 @@ K_ITEM *find_payouts_wid(int64_t workinfoidend, K_TREE_CTX *ctx) ctx = ctx0; payouts.workinfoidend = workinfoidend+1; - payouts.expirydate.tv_sec = 0; - payouts.expirydate.tv_usec = 0; + DATE_ZERO(&(payouts.expirydate)); INIT_PAYOUTS(&look); look.data = (void *)(&payouts); @@ -3319,9 +3462,9 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) PAYMENTS *payments; WORKINFO *workinfo; PAYOUTS *payouts, *payouts2; - BLOCKS *blocks, *blocks2; + BLOCKS *blocks; USERS *users; - K_ITEM *p_item, *old_p_item, *b_item, *b2_item, *w_item, *wb_item; + K_ITEM *p_item, *old_p_item, *b_item, *w_item, *wb_item; K_ITEM *u_item, *mu_item, *oc_item, *pay_item, *p2_item, *old_p2_item; SHARESUMMARY looksharesummary, *sharesummary; WORKMARKERS lookworkmarkers, *workmarkers; @@ -3369,28 +3512,16 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) // Check the block status K_RLOCK(blocks_free); b_item = find_blocks(height, blockhash, b_ctx); + K_RUNLOCK(blocks_free); if (!b_item) { - K_RUNLOCK(blocks_free); LOGERR("%s(): no block %"PRId32"/%s for payout", __func__, height, blockhash); goto oku; } DATA_BLOCKS(blocks, b_item); - b2_item = find_blocks_new(b_item, b_ctx); - K_RUNLOCK(blocks_free); - if (!b2_item) { - LOGEMERG("%s(): missing %s record for block %"PRId32 - "/%"PRId64"/%s/%s/%"PRId64, - __func__, blocks_confirmed(BLOCKS_NEW_STR), - blocks->height, blocks->workinfoid, - blocks->workername, blocks->confirmed, - blocks->reward); - goto oku; - } - DATA_BLOCKS(blocks2, b2_item); - copy_tv(&end_tv, &(blocks2->createdate)); + copy_tv(&end_tv, &(blocks->blockcreatedate)); if (!addr_cd) - addr_cd = &(blocks2->createdate); + addr_cd = &(blocks->blockcreatedate); LOGDEBUG("%s(): block %"PRId32"/%"PRId64"/%s/%s/%"PRId64, __func__, blocks->height, blocks->workinfoid, @@ -3421,11 +3552,11 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) // Get the PPLNS N values K_RLOCK(optioncontrol_free); - oc_item = find_optioncontrol(PPLNSDIFFTIMES, &(blocks->createdate), + oc_item = find_optioncontrol(PPLNSDIFFTIMES, &(blocks->blockcreatedate), height); K_RUNLOCK(optioncontrol_free); if (!oc_item) { - tv_to_buf(&(blocks->createdate), cd_buf, sizeof(cd_buf)); + tv_to_buf(&(blocks->blockcreatedate), cd_buf, sizeof(cd_buf)); LOGEMERG("%s(): missing optioncontrol %s (%s/%"PRId32")", __func__, PPLNSDIFFTIMES, cd_buf, blocks->height); goto oku; @@ -3434,11 +3565,11 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) diff_times = atof(optioncontrol->optionvalue); K_RLOCK(optioncontrol_free); - oc_item = find_optioncontrol(PPLNSDIFFADD, &(blocks->createdate), + oc_item = find_optioncontrol(PPLNSDIFFADD, &(blocks->blockcreatedate), height); K_RUNLOCK(optioncontrol_free); if (!oc_item) { - tv_to_buf(&(blocks->createdate), cd_buf, sizeof(cd_buf)); + tv_to_buf(&(blocks->blockcreatedate), cd_buf, sizeof(cd_buf)); LOGEMERG("%s(): missing optioncontrol %s (%s/%"PRId32")", __func__, PPLNSDIFFADD, cd_buf, blocks->height); goto oku; @@ -3489,7 +3620,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) end_workinfoid = sharesummary->workinfoid; /* Add up all sharesummaries until >= diff_want * also record the latest lastshare - that will be the end pplns time - * which will be >= blocks->createdate */ + * which will be >= blocks->blockcreatedate */ while (total_diff < diff_want && ss_item) { switch (sharesummary->complete[0]) { case SUMMARY_CONFIRM: @@ -3692,7 +3823,7 @@ bool process_pplns(int32_t height, char *blockhash, tv_t *addr_cd) bzero(payouts, sizeof(*payouts)); payouts->height = height; STRNCPY(payouts->blockhash, blockhash); - copy_tv(&(payouts->blockcreatedate), &(blocks2->createdate)); + copy_tv(&(payouts->blockcreatedate), &(blocks->blockcreatedate)); d64 = blocks->reward * 9 / 1000; g64 = blocks->reward - d64; payouts->minerreward = g64; @@ -4424,8 +4555,7 @@ static bool gen_workmarkers(PGconn *conn, MARKS *stt, bool after, MARKS *fin, look.data = (void *)(&workinfo); K_RLOCK(workinfo_free); if (before) { - workinfo.expirydate.tv_sec = 0; - workinfo.expirydate.tv_usec = 0; + DATE_ZERO(&(workinfo.expirydate)); wi_fin_item = find_before_in_ktree(workinfo_root, &look, cmp_workinfo, ctx); while (wi_fin_item) { @@ -5021,7 +5151,7 @@ void _userinfo_update(SHARES *shares, SHARESUMMARY *sharesummary, } // N.B. good blocks = blocks - (orphans + rejects) -void _userinfo_block(BLOCKS *blocks, enum info_type isnew, bool lock) +void _userinfo_block(BLOCKS *blocks, enum info_type isnew, int delta, bool lock) { USERINFO *row; K_ITEM *item; @@ -5031,12 +5161,12 @@ void _userinfo_block(BLOCKS *blocks, enum info_type isnew, bool lock) if (lock) K_WLOCK(userinfo_free); if (isnew == INFO_NEW) { - row->blocks++; + row->blocks += delta; copy_tv(&(row->last_block), &(blocks->createdate)); } else if (isnew == INFO_ORPHAN) - row->orphans++; + row->orphans += delta; else if (isnew == INFO_REJECT) - row->rejects++; + row->rejects += delta; if (lock) K_WUNLOCK(userinfo_free); diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index e6552ed2..7c6e4a6b 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -1079,11 +1079,11 @@ K_ITEM *useratts_add(PGconn *conn, char *username, char *attname, else TXT_TO_BIGINT("attnum2", attnum2, row->attnum2); if (attdate == NULL || attdate[0] == '\0') - row->attdate.tv_sec = row->attdate.tv_usec = 0L; + DATE_ZERO(&(row->attdate)); else TXT_TO_TV("attdate", attdate, row->attdate); if (attdate2 == NULL || attdate2[0] == '\0') - row->attdate2.tv_sec = row->attdate2.tv_usec = 0L; + DATE_ZERO(&(row->attdate2)); else TXT_TO_TV("attdate2", attdate2, row->attdate2); @@ -2922,7 +2922,8 @@ bool workinfo_fill(PGconn *conn) if (!ok) { free_workinfo_data(item); k_add_head(workinfo_free, item); - } + } else + ok = set_prevcreatedate(0); //K_WUNLOCK(workinfo_free); PQclear(res); @@ -4299,6 +4300,7 @@ unparam: blocks_root = add_to_ktree(blocks_root, b_item, cmp_blocks); k_add_head(blocks_store, b_item); blocks_stats_rebuild = true; + // 'confirmed' is unchanged so no need to recalc *createdate } K_WUNLOCK(blocks_free); @@ -4439,7 +4441,7 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash, } // We didn't use a Begin ok = true; - userinfo_block(row, INFO_NEW); + userinfo_block(row, INFO_NEW, 1); goto unparam; break; case BLOCKS_ORPHAN: @@ -4598,10 +4600,49 @@ bool blocks_add(PGconn *conn, char *height, char *blockhash, } update_old = true; - if (confirmed[0] == BLOCKS_ORPHAN) - userinfo_block(row, INFO_ORPHAN); - else if (confirmed[0] == BLOCKS_REJECT) - userinfo_block(row, INFO_REJECT); + /* handle confirmed state changes for userinfo + * this case statement handles all possible combinations + * even if they can't happen (yet) */ + switch (oldblocks->confirmed[0]) { + case BLOCKS_ORPHAN: + switch (confirmed[0]) { + case BLOCKS_ORPHAN: + break; + case BLOCKS_REJECT: + userinfo_block(row, INFO_ORPHAN, -1); + userinfo_block(row, INFO_REJECT, 1); + break; + default: + userinfo_block(row, INFO_ORPHAN, -1); + break; + } + break; + case BLOCKS_REJECT: + switch (confirmed[0]) { + case BLOCKS_REJECT: + break; + case BLOCKS_ORPHAN: + userinfo_block(row, INFO_REJECT, -1); + userinfo_block(row, INFO_ORPHAN, 1); + break; + default: + userinfo_block(row, INFO_REJECT, -1); + break; + } + break; + default: + switch (confirmed[0]) { + case BLOCKS_ORPHAN: + userinfo_block(row, INFO_ORPHAN, 1); + break; + case BLOCKS_REJECT: + userinfo_block(row, INFO_REJECT, 1); + break; + default: + break; + } + break; + } break; default: LOGERR("%s(): %s.failed.invalid confirm='%s'", @@ -4639,6 +4680,9 @@ flail: blocks_root = add_to_ktree(blocks_root, b_item, cmp_blocks); k_add_head(blocks_store, b_item); blocks_stats_rebuild = true; + // recalc the *createdate fields for possibly affected blocks + set_blockcreatedate(row->height); + set_prevcreatedate(row->height); } K_WUNLOCK(blocks_free); @@ -4712,6 +4756,7 @@ bool blocks_fill(PGconn *conn) { ExecStatusType rescode; PGresult *res; + K_TREE_CTX ctx[1]; K_ITEM *item; int n, i; BLOCKS *row; @@ -4863,16 +4908,30 @@ bool blocks_fill(PGconn *conn) pool.height = row->height; } - if (CURRENT(&(row->expirydate))) { - _userinfo_block(row, INFO_NEW, false); - if (row->confirmed[0] == BLOCKS_ORPHAN) - _userinfo_block(row, INFO_ORPHAN, false); - else if (row->confirmed[0] == BLOCKS_REJECT) - _userinfo_block(row, INFO_REJECT, false); - } + // first add all the NEW blocks + if (row->confirmed[0] == BLOCKS_NEW) + _userinfo_block(row, INFO_NEW, 1, false); } + if (!ok) k_add_head(blocks_free, item); + else + ok = set_blockcreatedate(0); + + // Now update all the CURRENT orphan/reject stats + if (ok) { + item = first_in_ktree(blocks_root, ctx); + while (item) { + DATA_BLOCKS(row, item); + if (CURRENT(&(row->expirydate))) { + if (row->confirmed[0] == BLOCKS_ORPHAN) + _userinfo_block(row, INFO_ORPHAN, 1, false); + else if (row->confirmed[0] == BLOCKS_REJECT) + _userinfo_block(row, INFO_REJECT, 1, false); + } + item = next_in_ktree(ctx); + } + } K_WUNLOCK(blocks_free); PQclear(res); @@ -5506,7 +5565,7 @@ bool payouts_fill(PGconn *conn) { ExecStatusType rescode; PGresult *res; - K_ITEM *item, *b_item, *b2_item; + K_ITEM *item, *b_item; K_TREE_CTX ctx[1]; PAYOUTS *row; BLOCKS *blocks; @@ -5633,17 +5692,10 @@ bool payouts_fill(PGconn *conn) ok = false; break; } else { - b2_item = find_blocks_new(b_item, ctx); - if (!b2_item) { - LOGERR("%s(): payoutid %"PRId64" references " - "block %"PRId32"/%s that has no NEW", - __func__, row->payoutid, row->height, - row->blockhash); - ok = false; - break; - } - DATA_BLOCKS(blocks, b2_item); - copy_tv(&(row->blockcreatedate), &(blocks->createdate)); + // blockcreatedate will already be set + DATA_BLOCKS(blocks, b_item); + copy_tv(&(row->blockcreatedate), + &(blocks->blockcreatedate)); } payouts_root = add_to_ktree(payouts_root, item, cmp_payouts); From 6adbec85506e916b025ff41e7b8eed6a2630f3b2 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 5 Sep 2015 03:15:33 +1000 Subject: [PATCH 23/27] cdb/php - add a red line under the last payout on the shifts page --- pool/inc.php | 2 ++ pool/page_shifts.php | 8 ++++++-- src/ckdb.h | 2 +- src/ckdb_cmd.c | 13 ++++++++++++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/pool/inc.php b/pool/inc.php index ad8819a0..5ae064df 100644 --- a/pool/inc.php +++ b/pool/inc.php @@ -117,7 +117,9 @@ h1 {margin-top:20px;float:middle;font-size:20px;} .foot, .push {height:50px;} .title {background-color:#909090;} .even {background-color:#cccccc;} +.evenu td {background-color:#cccccc;border-bottom:2px solid red;} .odd {background-color:#a8a8a8;} +.oddu td {background-color:#a8a8a8;border-bottom:2px solid red;} .hid {display:none;} .dl {text-align:left;padding:2px 8px;} .dr {text-align:right;padding:2px 8px;} diff --git a/pool/page_shifts.php b/pool/page_shifts.php index 40cc94ff..1be0d587 100644 --- a/pool/page_shifts.php +++ b/pool/page_shifts.php @@ -27,10 +27,14 @@ function doshifts($data, $user) $pg = '

    Last '.($count+1).' Shifts

    '.$pg; for ($i = 0; $i < $count; $i++) { + $u = ''; + if (isset($ans['lastpayoutstart:'.$i]) + && $ans['lastpayoutstart:'.$i] != '') + $u = 'u'; if (($i % 2) == 0) - $row = 'even'; + $row = "even$u"; else - $row = 'odd'; + $row = "odd$u"; $pg .= "
    "; $shifname = $ans['shift:'.$i]; diff --git a/src/ckdb.h b/src/ckdb.h index e98cf5ef..7a5448be 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.232" +#define CKDB_VERSION DB_VERSION"-1.233" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index f724b218..a94abd60 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -5143,6 +5143,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, int rows, want, i, where_all; int64_t maxrows; double wm_count, d; + int64_t last_payout_start = 0; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -5169,6 +5170,7 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, wm_count *= 1.42; if (maxrows < wm_count) maxrows = wm_count; + last_payout_start = payouts->workinfoidstart; } i_select = optional_name(trf_root, "select", 1, NULL, reply, siz); @@ -5360,6 +5362,14 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, rows, wm->rewards, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "lastpayoutstart:%d=%s%c", + rows, + (wm->workinfoidstart == + last_payout_start) ? + "Y" : EMPTY, + FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + rows++; // Setup for next shift @@ -5399,7 +5409,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id, * other workers start >= 0 and finish <= rows-1 */ snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c", rows, FLDSEP, - "markerid,shift,start,end,rewards", FLDSEP); + "markerid,shift,start,end,rewards," + "lastpayoutstart", FLDSEP); APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts"); From 9c0adf9e15bc038d925e88648de06c7b7bbd46ed Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 5 Sep 2015 03:20:03 +1000 Subject: [PATCH 24/27] php - add '3' addresses to address only pages --- pool/address.php | 3 ++- pool/worker.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pool/address.php b/pool/address.php index 625f08fb..01c840cd 100644 --- a/pool/address.php +++ b/pool/address.php @@ -8,7 +8,8 @@ include_once('param.php'); function go() { $a = getparam('a', true); - if (substr($a, 0, 1) != '1') + $f = substr($a, 0, 1); + if ($f != '1' and $f != '3') return; if (strlen($a) < 24) return; diff --git a/pool/worker.php b/pool/worker.php index dc7ef16c..5cc393cf 100644 --- a/pool/worker.php +++ b/pool/worker.php @@ -8,7 +8,8 @@ include_once('param.php'); function go() { $a = getparam('a', true); - if (substr($a, 0, 1) != '1') + $f = substr($a, 0, 1); + if ($f != '1' and $f != '3') return; if (preg_match('/^[a-zA-Z0-9]{24,}[\._]?[a-zA-Z0-9\._]*$/', $a) === false) return; From dd2bc34e7b397ea0caa1af3e5ab54fa0ccb43487 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 5 Sep 2015 10:13:34 +1000 Subject: [PATCH 25/27] php - age doesn't include the current unfound block - so rename it as 'Time' --- pool/page_blocks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pool/page_blocks.php b/pool/page_blocks.php index 73df3c55..e8d473bd 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -93,7 +93,7 @@ function doblocks($data, $user) $pg .= "
    BlockBlock UTCMiner RewardN DiffN Range
    '.$ans['height:'.$i].''.gmdate('d/M H:i',$ans['blockcreatedate:'.$i]).''.btcfmt($ans['minerreward:'.$i]).''.difffmt($diffused).'
    Total:'.btcfmt($totamt).'
    Luck%
    $desc Blocks$age$age$diff%$mean%$cdferldsp
    '.$ans['height:'.$i].''.gmdate('d/M H:i',$ans['blockcreatedate:'.$i]).''.gmdate('j/M H:i',$ans['blockcreatedate:'.$i]).''.btcfmt($ans['minerreward:'.$i]).''.difffmt($diffused).'
    \n"; $pg .= ""; $pg .= ""; - $pg .= ""; + $pg .= ""; $pg .= ""; $pg .= ""; $pg .= ""; From 3c6b81fd67a8798a8cc5563783710a103a6caef7 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 6 Sep 2015 22:22:41 +1000 Subject: [PATCH 26/27] ckdb/php - allow cancelling 2fa setup and removing 2fa directly --- pool/email.php | 42 +++++++++++++++++++++++++- pool/page_2fa.php | 77 ++++++++++++++++++++++++++++++++++------------- src/ckdb.h | 5 +-- src/ckdb_cmd.c | 21 ++++++++++++- src/ckdb_crypt.c | 9 ++++-- 5 files changed, 126 insertions(+), 28 deletions(-) diff --git a/pool/email.php b/pool/email.php index db4f5540..1e1d36f2 100644 --- a/pool/email.php +++ b/pool/email.php @@ -186,7 +186,7 @@ function twofaSetup($to, $whoip, $emailinfo) return false; $message = "2FA is ready to be tested.$eol"; - $message = "It will be enabled once you test it.$eol$eol"; + $message .= "It will be enabled once you test it.$eol$eol"; $message .= $ret; return sendnoheader($to, "2FA is Ready to be Enabled", $message, $emailinfo); @@ -211,6 +211,46 @@ function twofaEnabled($to, $whoip, $emailinfo) return sendnoheader($to, "2FA is Enabled", $message, $emailinfo); } # +function twofaCancel($to, $whoip, $emailinfo) +{ + global $eol; + + if (!isset($emailinfo['KWebURL'])) + return false; + + $web = $emailinfo['KWebURL']; + + $ret = emailEnd('2fa change', $whoip, $emailinfo); + if ($ret === false) + return false; + + $message = "2FA setup was cancelled on your account.$eol"; + $message .= "You can set it up later if you want.$eol$eol"; + $message .= $ret; + + return sendnoheader($to, "2FA was Cancelled", $message, $emailinfo); +} +# +function twofaRemove($to, $whoip, $emailinfo) +{ + global $eol; + + if (!isset($emailinfo['KWebURL'])) + return false; + + $web = $emailinfo['KWebURL']; + + $ret = emailEnd('2fa change', $whoip, $emailinfo); + if ($ret === false) + return false; + + $message = "2FA was removed from your account.$eol"; + $message .= "You can set it up again later if you want.$eol$eol"; + $message .= $ret; + + return sendnoheader($to, "2FA was Removed", $message, $emailinfo); +} +# # getOpts required for email # If they aren't all setup in the DB then email functions will return false function emailOptList() diff --git a/pool/page_2fa.php b/pool/page_2fa.php index 4ec7330a..37e1ff2d 100644 --- a/pool/page_2fa.php +++ b/pool/page_2fa.php @@ -23,7 +23,6 @@ function set_2fa($data, $user, $tfa, $ans, $err) $pg .= '
    DescriptionAgeTimeDiff%Mean%CDF[Erl]
    '; $pg .= '
    '; - $pg .= makeForm('2fa'); $pg .= ''; $pg .= ''; + $pg .= ''; break; case 'test': $pg .= ''; + $pg .= ''; $pg .= ''; + $pg .= ''; break; case 'ok': $pg .= ''; + $pg .= ''; break; } - $pg .= '
    '; switch ($tfa) @@ -33,9 +32,10 @@ function set_2fa($data, $user, $tfa, $ans, $err) $pg .= "You don't have Two Factor Authentication (2FA) setup yet

    "; $pg .= 'To use 2FA you need an App on your phone/tablet
    '; $pg .= app_txt('ones'); + $pg .= makeForm('2fa'); $pg .= 'Click here to begin the setup process for 2FA: '; $pg .= ''; - $pg .= '
    '; @@ -66,8 +66,9 @@ function set_2fa($data, $user, $tfa, $ans, $err) $pg .= '
    '; $pg .= 'A qrcode will show here if your browser supports html5/canvas'; $pg .= "

    "; + $pg .= makeForm('2fa'); $pg .= 'Then enter your App 2FA Value: '; - $pg .= '
    '; $pg .= app_txt('2FA apps'); $pg .= 'N.B. if you wish to setup 2FA on more than one device,
    '; @@ -79,20 +80,32 @@ function set_2fa($data, $user, $tfa, $ans, $err) $pg .= 'so your should copy it and store it somewhere securely.
    '; $pg .= 'For security reasons, the site will not show you an active 2FA Secret Key.
    '; $pg .= '
    '; + $pg .= makeForm('2fa'); + $pg .= '
    If you wish to cancel setting up 2FA, click here: '; + $pg .= '
    '; $pg .= '2FA is enabled on your account.

    '; $pg .= 'If you wish to replace your Secret Key with a new one:

    '; + $pg .= makeForm('2fa'); $pg .= 'Current 2FA Value: '; - $pg .= '*

    '; + $pg .= '*'; + $pg .= '

    '; $pg .= '*WARNING: replacing the Secret Key will disable 2FA
    '; $pg .= 'until you successfully test the new key,
    '; $pg .= 'thus getting a new key is effectively the same as disabling 2FA.

    '; $pg .= '
    '; + $pg .= makeForm('2fa'); + $pg .= 'If you wish to remove 2FA from your account,
    '; + $pg .= 'enter your App 2FA Value:
    '; + $pg .= 'then click remove: '; + $pg .= '
    '; + $pg .= '
    '; $pg .= ''; $pg .= ''; @@ -147,34 +160,52 @@ function set_2fa($data, $user, $tfa, $ans, $err) # function do2fa($data, $user) { + $mailmode = ''; $err = ''; $setup = getparam('Setup', false); - $testemail = false; if ($setup === 'Setup') { // rand() included as part of the entropy $ans = get2fa($user, 'setup', rand(1073741824,2147483647), 0); - $testemail = true; + $mailmode = 'Setup'; } else { - $value = getparam('Value', false); - $test = getparam('Test', false); - if ($test === 'Test' and $value !== null) + $can = getparam('Cancel', false); + if ($can === 'Cancel') { - $ans = get2fa($user, 'test', 0, $value); - $testemail = true; + $ans = get2fa($user, 'untest', 0, 0); + $mailmode = 'Cancel'; } else { - $nw = getparam('New', false); - if ($nw === 'New' and $value !== null) + $value = getparam('Value', false); + $test = getparam('Test', false); + if ($test === 'Test' and $value !== null) { - $ans = get2fa($user, 'new', rand(1073741824,2147483647), $value); - $testemail = true; + $ans = get2fa($user, 'test', 0, $value); + $mailmode = 'Test'; } else - $ans = get2fa($user, '', 0, 0); + { + $nw = getparam('New', false); + if ($nw === 'New' and $value !== null) + { + $ans = get2fa($user, 'new', rand(1073741824,2147483647), $value); + $mailmode = 'New'; + } + else + { + $rem = getparam('Remove', false); + if ($rem === 'Remove' and $value !== null) + { + $ans = get2fa($user, 'remove', 0, $value); + $mailmode = 'Remove'; + } + else + $ans = get2fa($user, '', 0, 0); + } + } } } if ($ans['STATUS'] != 'ok') @@ -184,7 +215,7 @@ function do2fa($data, $user) if (isset($ans['2fa_error'])) $err = $ans['2fa_error']; - if ($testemail and $err == '') + if ($mailmode != '' and $err == '') { $ans2 = userSettings($user); if ($ans2['STATUS'] != 'ok') @@ -199,12 +230,16 @@ function do2fa($data, $user) $err = 'An error occurred, check your details below'; else { - if ($setup === 'Setup') + if ($mailmode === 'Setup') twofaSetup($email, zeip(), $emailinfo); - else if ($test === 'Test') + else if ($mailmode === 'Test') twofaEnabled($email, zeip(), $emailinfo); - else if ($nw === 'New') + else if ($mailmode === 'New') twofaSetup($email, zeip(), $emailinfo); + else if ($mailmode === 'Cancel') + twofaCancel($email, zeip(), $emailinfo); + else if ($mailmode === 'Remove') + twofaRemove($email, zeip(), $emailinfo); } } } diff --git a/src/ckdb.h b/src/ckdb.h index 7a5448be..fcb313c3 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.233" +#define CKDB_VERSION DB_VERSION"-1.240" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -2633,6 +2633,7 @@ extern bool check_2fa(USERS *users, int32_t value); extern bool tst_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root); extern K_ITEM *remove_2fa(K_ITEM *old_u_item, int32_t value, char *by, - char *code, char *inet, tv_t *cd, K_TREE *trf_root); + char *code, char *inet, tv_t *cd, K_TREE *trf_root, + bool check); #endif diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index a94abd60..7ad2e25b 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -301,9 +301,24 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, else { key = false; sfa_status = "ok"; + sfa_error = "2FA Enabled"; } // Report sfa_error to web ok = true; + } else if (strcmp(action, "untest") == 0) { + // Can't untest if it's not ready to test + if ((users->databits & (USER_TOTPAUTH | USER_TEST2FA)) + != (USER_TOTPAUTH | USER_TEST2FA)) + goto dame; + // since it's currently test, the value isn't required + u_new = remove_2fa(u_item, 0, by, code, inet, now, + trf_root, false); + if (u_new) { + ok = true; + sfa_status = EMPTY; + key = false; + sfa_error = "2FA Cancelled"; + } } else if (strcmp(action, "new") == 0) { // Can't new if 2FA isn't already present -> setup if ((users->databits & USER_TOTPAUTH) == 0) @@ -329,18 +344,22 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, // Can't remove if 2FA isn't already present if (!(users->databits & (USER_TOTPAUTH | USER_TEST2FA))) goto dame; + // remove requires value value = (int32_t)atoi(transfer_data(i_value)); if (!check_2fa(users, value)) { sfa_error = "Invalid code"; // Report sfa_error to web ok = true; } else { + /* already tested 2fa so don't retest, also, + * a retest will fail using the same value */ u_new = remove_2fa(u_item, value, by, code, - inet, now, trf_root); + inet, now, trf_root, false); if (u_new) { ok = true; sfa_status = EMPTY; key = false; + sfa_error = "2FA Removed"; } } } diff --git a/src/ckdb_crypt.c b/src/ckdb_crypt.c index d285e9ac..7ad0109f 100644 --- a/src/ckdb_crypt.c +++ b/src/ckdb_crypt.c @@ -237,14 +237,17 @@ bool tst_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code, } K_ITEM *remove_2fa(K_ITEM *old_u_item, int32_t value, char *by, char *code, - char *inet, tv_t *cd, K_TREE *trf_root) + char *inet, tv_t *cd, K_TREE *trf_root, bool check) { K_ITEM *u_item = NULL; USERS *old_users, *users; - bool ok, did = false; + bool ok = true, did = false; DATA_USERS(old_users, old_u_item); - ok = check_2fa(old_users, value); + /* N.B. check_2fa will fail if it is called a second time + * with the same value */ + if (check) + ok = check_2fa(old_users, value); if (ok) { K_WLOCK(users_free); u_item = k_unlink_head(users_free); From 8aa6841f615e3bdb01ec612e9ac9d7ea71040094 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 6 Sep 2015 23:04:37 +1000 Subject: [PATCH 27/27] ckdb/php - keep 2fa success messages seperate from errors --- pool/inc.php | 1 + pool/page_2fa.php | 11 +++++++++-- src/ckdb.h | 2 +- src/ckdb_cmd.c | 13 +++++++------ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pool/inc.php b/pool/inc.php index 5ae064df..c855da5f 100644 --- a/pool/inc.php +++ b/pool/inc.php @@ -99,6 +99,7 @@ span.hdr {font-weight:bold;text-decoration:underline;} span.nn {font-weight:bold;color:red;} span.warn {color:orange;font-weight:bold;} span.urg {color:red;font-weight:bold;} +span.notice {color:blue;font-weight:bold;font-size:120%;} span.err {color:red;font-weight:bold;font-size:120%;} span.alert {color:red;font-weight:bold;font-size:250%;} input.tiny {width:0px;height:0px;margin:0px;padding:0px;outline:none;border:0px;} diff --git a/pool/page_2fa.php b/pool/page_2fa.php index 37e1ff2d..6687846d 100644 --- a/pool/page_2fa.php +++ b/pool/page_2fa.php @@ -11,7 +11,7 @@ function app_txt($ones) return $app; } # -function set_2fa($data, $user, $tfa, $ans, $err) +function set_2fa($data, $user, $tfa, $ans, $err, $msg) { $draw = false; @@ -20,6 +20,9 @@ function set_2fa($data, $user, $tfa, $ans, $err) if ($err !== null and $err != '') $pg .= "$err

    "; + if ($msg !== null and $msg != '') + $pg .= "$msg

    "; + $pg .= ''; $pg .= '
    '; @@ -162,6 +165,7 @@ function do2fa($data, $user) { $mailmode = ''; $err = ''; + $msg = ''; $setup = getparam('Setup', false); if ($setup === 'Setup') { @@ -248,7 +252,10 @@ function do2fa($data, $user) $tfa = null; else $tfa = $ans['2fa_status']; - $pg = set_2fa($data, $user, $tfa, $ans, $err); + if (isset($ans['2fa_msg'])) + $msg = $ans['2fa_msg']; + + $pg = set_2fa($data, $user, $tfa, $ans, $err, $msg); return $pg; } # diff --git a/src/ckdb.h b/src/ckdb.h index fcb313c3..af0ff79e 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.2" -#define CKDB_VERSION DB_VERSION"-1.240" +#define CKDB_VERSION DB_VERSION"-1.241" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index 7ad2e25b..f4911289 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -213,7 +213,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, int32_t entropy, value; USERS *users; char *action, *buf = NULL, *st = NULL; - char *sfa_status = EMPTY, *sfa_error = EMPTY; + char *sfa_status = EMPTY, *sfa_error = EMPTY, *sfa_msg = EMPTY; bool ok = false, key = false; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -301,7 +301,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, else { key = false; sfa_status = "ok"; - sfa_error = "2FA Enabled"; + sfa_msg = "2FA Enabled"; } // Report sfa_error to web ok = true; @@ -317,7 +317,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, ok = true; sfa_status = EMPTY; key = false; - sfa_error = "2FA Cancelled"; + sfa_msg = "2FA Cancelled"; } } else if (strcmp(action, "new") == 0) { // Can't new if 2FA isn't already present -> setup @@ -359,7 +359,7 @@ static char *cmd_2fa(__maybe_unused PGconn *conn, char *cmd, char *id, ok = true; sfa_status = EMPTY; key = false; - sfa_error = "2FA Removed"; + sfa_msg = "2FA Removed"; } } } @@ -430,8 +430,9 @@ dame: return strdup("failed."); } - snprintf(tmp, sizeof(tmp), "2fa_status=%s%c2fa_error=%s", - sfa_status, FLDSEP, sfa_error); + snprintf(tmp, sizeof(tmp), "2fa_status=%s%c2fa_error=%s%c2fa_msg=%s", + sfa_status, FLDSEP, sfa_error, FLDSEP, + sfa_msg); APPEND_REALLOC(buf, off, len, tmp); LOGDEBUG("%s.%s-%s.%s", id, transfer_data(i_username), action, buf); return buf;