From 1ae5e57fc4cd9df43688a71096b101ea2cebe965 Mon Sep 17 00:00:00 2001 From: Ben U Date: Sat, 8 Nov 2014 14:17:15 -0700 Subject: [PATCH 1/9] Fixed mobile menu bar with proper spacing. --- pool/page.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pool/page.php b/pool/page.php index d1183b4b..5d0d7d44 100644 --- a/pool/page.php +++ b/pool/page.php @@ -110,8 +110,8 @@ 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;} #n42 {margin:0; position: relative; color:#fff; background:#07e;} -#n42 a {color:#fff; text-decoration:none; margin: 4px;} -#n42 td {min-width: 100px; float: left; vertical-align: top; padding: 2px;} +#n42 a {color:#fff; text-decoration:none; padding: 8px; display:block;} +#n42 td {min-width: 100px; float: left; vertical-align: top; padding: 0px 2px;} #n42 td.navboxr {float: right;} #n42 td.nav {position: relative;} #n42 div.sub {left: 0px; z-index: 42; position: absolute; visibility: hidden;} From 03efdd03323660138b537d9ae3fef591f0c51986 Mon Sep 17 00:00:00 2001 From: kanoi Date: Tue, 18 Nov 2014 12:29:10 +1100 Subject: [PATCH 2/9] ckdb - disallow web usernames like BTC addresses --- src/ckdb.c | 8 ++++++-- src/ckdb.h | 11 ++++++++++- src/ckdb_cmd.c | 37 +++++++++++++++++++++++++------------ src/ckdb_data.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 3554a11e..c43ae064 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -174,8 +174,12 @@ const char *mailpatt = "^[A-Za-z0-9_-][A-Za-z0-9_\\.-]*@[A-Za-z0-9][A-Za-z0-9\\. const char *idpatt = "^[_A-Za-z][_A-Za-z0-9]*$"; const char *intpatt = "^[0-9][0-9]*$"; const char *hashpatt = "^[A-Fa-f0-9]*$"; -// TODO: bitcoind will check it properly -const char *addrpatt = "^[A-Za-z0-9]*$"; +/* BTC addresses start with '1' (one) or '3' (three), + * exclude: capital 'I' (eye), capital 'O' (oh), + * lowercase 'l' (elle) and '0' (zero) + * and with a simple test must be ADDR_MIN_LEN to ADDR_MAX_LEN (ckdb.h) + * bitcoind is used to fully validate them when required */ +const char *addrpatt = "^[13][A-HJ-NP-Za-km-z1-9]*$"; // So the records below have the same 'name' as the klist const char Transfer[] = "Transfer"; diff --git a/src/ckdb.h b/src/ckdb.h index dd245ef3..f9a216c0 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.631" +#define CKDB_VERSION DB_VERSION"-0.640" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -80,6 +80,14 @@ extern const char *intpatt; extern const char *hashpatt; extern const char *addrpatt; +/* If a trimmed username is like an address but this many or more characters, + * disallow it */ +#define ADDR_USER_CHECK 16 + +// BTC address size +#define ADDR_MIN_LEN 26 +#define ADDR_MAX_LEN 34 + typedef struct loadstatus { tv_t oldest_sharesummary_firstshare_n; tv_t newest_sharesummary_firstshare_a; @@ -1334,6 +1342,7 @@ extern PGconn *dbconnect(); extern char *safe_text(char *txt); extern void username_trim(USERS *users); +extern bool like_address(char *username); extern void _txt_to_data(enum data_type typ, char *nam, char *fld, void *data, size_t siz, WHERE_FFL_ARGS); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index c7c580c8..e3443858 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -15,7 +15,7 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, { char reply[1024] = ""; size_t siz = sizeof(reply); - K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item; + K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item = NULL; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -23,18 +23,30 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, if (!i_username) return strdup(reply); - i_emailaddress = require_name(trf_root, "emailaddress", 7, (char *)mailpatt, reply, siz); - if (!i_emailaddress) - return strdup(reply); + /* If a username added from the web site looks like an address + * then disallow it - a false positive is not an issue + * Allowing it will create a security issue - someone could create + * an account with someone else's, as yet unused, payout address + * and redirect the payout to another payout address. + * ... and the person who owns the payout address can't check that + * in advance, they'll just find out with their first payout not + * arriving at their payout address */ + if (!like_address(transfer_data(i_username))) { + i_emailaddress = require_name(trf_root, "emailaddress", 7, + (char *)mailpatt, reply, siz); + if (!i_emailaddress) + return strdup(reply); - i_passwordhash = require_name(trf_root, "passwordhash", 64, (char *)hashpatt, reply, siz); - if (!i_passwordhash) - return strdup(reply); + i_passwordhash = require_name(trf_root, "passwordhash", 64, + (char *)hashpatt, reply, siz); + if (!i_passwordhash) + return strdup(reply); - u_item = users_add(conn, transfer_data(i_username), - transfer_data(i_emailaddress), - transfer_data(i_passwordhash), - by, code, inet, now, trf_root); + u_item = users_add(conn, transfer_data(i_username), + transfer_data(i_emailaddress), + transfer_data(i_passwordhash), + by, code, inet, now, trf_root); + } if (!u_item) { LOGERR("%s() %s.failed.DBE", __func__, id); @@ -223,7 +235,8 @@ static char *cmd_userset(PGconn *conn, char *cmd, char *id, email = NULL; } i_address = optional_name(trf_root, "address", - 27, (char *)addrpatt, + ADDR_MIN_LEN, + (char *)addrpatt, reply, siz); if (i_address) address = transfer_data(i_address); diff --git a/src/ckdb_data.c b/src/ckdb_data.c index e712f520..b799648d 100644 --- a/src/ckdb_data.c +++ b/src/ckdb_data.c @@ -67,6 +67,55 @@ void username_trim(USERS *users) } } +/* Is the trimmed username like an address? + * False positive is OK (i.e. 'like') + * Before checking, it is trimmed to avoid web display confusion + * Length check is done before trimming - this may give a false + * positive on any username with lots of trim characters ... which is OK */ +bool like_address(char *username) +{ + char *tmp, *front, *trail; + size_t len; + regex_t re; + int ret; + + len = strlen(username); + if (len < ADDR_USER_CHECK) + return false; + + tmp = strdup(username); + front = tmp; + while (*front && TRIM_IGNORE(*front)) + front++; + + trail = front + strlen(front) - 1; + while (trail >= front) { + if (TRIM_IGNORE(*trail)) + *(trail--) = '\0'; + else + break; + } + + if (regcomp(&re, addrpatt, REG_NOSUB) != 0) { + LOGEMERG("%s(): failed to compile addrpatt '%s'", + __func__, addrpatt); + free(tmp); + // This will disable adding any new usernames ... + return true; + } + + ret = regexec(&re, front, (size_t)0, NULL, 0); + regfree(&re); + + if (ret == 0) { + free(tmp); + return true; + } + + free(tmp); + return false; +} + void _txt_to_data(enum data_type typ, char *nam, char *fld, void *data, size_t siz, WHERE_FFL_ARGS) { char *tmp; From 7a8392bb1fbebe1e278f9a9df831e7dcd67042ff Mon Sep 17 00:00:00 2001 From: kanoi Date: Tue, 18 Nov 2014 12:35:41 +1100 Subject: [PATCH 3/9] ckdb - suggest to malloc to use mmap for transfer --- src/ckdb.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index f9a216c0..61848f18 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.640" +#define CKDB_VERSION DB_VERSION"-0.641" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -611,7 +611,8 @@ typedef struct transfer { char *mvalue; } TRANSFER; -#define ALLOC_TRANSFER 64 +// Suggest malloc use MMAP - 1913 = largest under 2MB +#define ALLOC_TRANSFER 1913 #define LIMIT_TRANSFER 0 #define CULL_TRANSFER 1024 #define INIT_TRANSFER(_item) INIT_GENERIC(_item, transfer) From 5d522ddec836b6d208780dac45f4a37bee12acab Mon Sep 17 00:00:00 2001 From: kanoi Date: Tue, 18 Nov 2014 12:49:29 +1100 Subject: [PATCH 4/9] ckdb - fail auth if users.status isn't empty --- src/ckdb.h | 2 +- src/ckdb_dbio.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ckdb.h b/src/ckdb.h index 61848f18..bb35f06d 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.641" +#define CKDB_VERSION DB_VERSION"-0.642" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 8c0b3d52..f837e78b 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -4055,6 +4055,10 @@ bool auths_add(PGconn *conn, char *poolinstance, char *username, } DATA_USERS(*users, u_item); + // Any status content means disallow mining + if ((*users)->status[0]) + goto unitem; + STRNCPY(row->poolinstance, poolinstance); row->userid = (*users)->userid; // since update=false, a dup will be ok and do nothing when igndup=true From 27b722e66e4aa4601747cd1c69646cb5fd6ce897 Mon Sep 17 00:00:00 2001 From: kanoi Date: Tue, 18 Nov 2014 18:24:19 +1100 Subject: [PATCH 5/9] ckdb - allow disabling/enabling users --- src/ckdb.c | 9 +++++ src/ckdb.h | 11 +++--- src/ckdb_cmd.c | 91 ++++++++++++++++++++++++++++++++++++++++++------- src/ckdb_dbio.c | 28 +++++++++------ 4 files changed, 111 insertions(+), 28 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index c43ae064..11a0274f 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -2052,6 +2052,7 @@ static void *socketer(__maybe_unused void *arg) char *last_newid = NULL, *reply_newid = NULL; char *last_setatts = NULL, *reply_setatts = NULL; char *last_setopts = NULL, *reply_setopts = NULL; + char *last_userstatus = NULL, *reply_userstatus = NULL; char *last_web = NULL, *reply_web = NULL; char *reply_last, duptype[CMD_SIZ+1]; enum cmd_values cmdnum; @@ -2155,6 +2156,9 @@ static void *socketer(__maybe_unused void *arg) } else if (last_setopts && strcmp(last_setopts, buf) == 0) { reply_last = reply_setopts; dup = true; + } else if (last_userstatus && strcmp(last_userstatus, buf) == 0) { + reply_last = reply_userstatus; + dup = true; } else if (last_web && strcmp(last_web, buf) == 0) { reply_last = reply_web; dup = true; @@ -2255,6 +2259,7 @@ static void *socketer(__maybe_unused void *arg) case CMD_BLOCKLIST: case CMD_NEWID: case CMD_STATS: + case CMD_USERSTATUS: ans = ckdb_cmds[which_cmds].func(NULL, cmd, id, &now, by_default, (char *)__func__, @@ -2297,6 +2302,9 @@ static void *socketer(__maybe_unused void *arg) case CMD_SETOPTS: STORELASTREPLY(setopts); break; + case CMD_USERSTATUS: + STORELASTREPLY(userstatus); + break; // The rest default: free(rep); @@ -2503,6 +2511,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) case CMD_DSP: case CMD_STATS: case CMD_PPLNS: + case CMD_USERSTATUS: LOGERR("%s() Message line %"PRIu64" '%s' - invalid - ignored", __func__, count, cmd); break; diff --git a/src/ckdb.h b/src/ckdb.h index bb35f06d..e7341af0 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.642" +#define CKDB_VERSION DB_VERSION"-0.643" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -303,6 +303,7 @@ enum cmd_values { CMD_DSP, CMD_STATS, CMD_PPLNS, + CMD_USERSTATUS, CMD_END }; @@ -641,7 +642,7 @@ typedef struct users { int64_t userid; char username[TXT_BIG+1]; char usertrim[TXT_BIG+1]; // Non DB field - // TODO: Anything in 'status' disables the account + // Anything in 'status' fails mining authentication char status[TXT_BIG+1]; char emailaddress[TXT_BIG+1]; tv_t joineddate; @@ -1544,9 +1545,9 @@ extern char *pqerrmsg(PGconn *conn); extern int64_t nextid(PGconn *conn, char *idname, int64_t increment, tv_t *cd, char *by, char *code, char *inet); -extern bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash, - char *newhash, char *email, char *by, char *code, - char *inet, tv_t *cd, K_TREE *trf_root); +extern bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash, + char *newhash, char *email, char *by, char *code, + char *inet, tv_t *cd, K_TREE *trf_root, char *status); extern K_ITEM *users_add(PGconn *conn, char *username, char *emailaddress, char *passwordhash, char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root); diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index e3443858..53d9cbef 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -97,12 +97,13 @@ static char *cmd_newpass(__maybe_unused PGconn *conn, char *cmd, char *id, K_RUNLOCK(users_free); if (u_item) { - ok = users_pass_email(NULL, u_item, - oldhash, - transfer_data(i_newhash), - NULL, - by, code, inet, now, - trf_root); + ok = users_update(NULL, u_item, + oldhash, + transfer_data(i_newhash), + NULL, + by, code, inet, now, + trf_root, + NULL); } else ok = false; } @@ -261,10 +262,12 @@ static char *cmd_userset(PGconn *conn, char *cmd, char *id, } if (email && *email) { - ok = users_pass_email(conn, u_item, NULL, - NULL, email, - by, code, inet, - now, trf_root); + ok = users_update(conn, u_item, + NULL, NULL, + email, + by, code, inet, now, + trf_root, + NULL); if (!ok) { reason = "email error"; goto struckout; @@ -3392,6 +3395,69 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id, return buf; } +// TODO: add to heartbeat to disable the miner if active and status != "" +static char *cmd_userstatus(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, + char *code, char *inet, __maybe_unused tv_t *cd, + K_TREE *trf_root) +{ + char reply[1024] = ""; + size_t siz = sizeof(reply); + K_ITEM *i_username, *i_userid, *i_status, *u_item; + int64_t userid; + char *status; + USERS *users; + bool ok; + + LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + + i_username = optional_name(trf_root, "username", 3, (char *)userpatt, reply, siz); + i_userid = optional_name(trf_root, "userid", 1, (char *)intpatt, reply, siz); + // Either username or userid + if (!i_username && !i_userid) { + snprintf(reply, siz, "failed.invalid/missing userinfo"); + LOGERR("%s.%s", id, reply); + return strdup(reply); + } + + // A zero length status re-enables it + i_status = require_name(trf_root, "status", 0, NULL, reply, siz); + if (!i_status) + return strdup(reply); + status = transfer_data(i_status); + + K_RLOCK(users_free); + if (i_username) + u_item = find_users(transfer_data(i_username)); + else { + TXT_TO_BIGINT("userid", transfer_data(i_userid), userid); + u_item = find_userid(userid); + } + K_RUNLOCK(users_free); + + if (!u_item) + ok = false; + else { + ok = users_update(conn, u_item, + NULL, NULL, + NULL, + by, code, inet, now, + trf_root, + status); + } + + if (!ok) { + LOGERR("%s() %s.failed.DBE", __func__, id); + return strdup("failed.DBE"); + } + DATA_USERS(users, u_item); + snprintf(reply, siz, "ok.updated %"PRId64" %s status %s", + users->userid, + users->username, + status[0] ? "disabled" : "enabled"); + LOGWARNING("%s.%s", id, reply); + return strdup(reply); +} + // TODO: limit access by having seperate sockets for each #define ACCESS_POOL "p" #define ACCESS_SYSTEM "s" @@ -3492,7 +3558,8 @@ struct CMDS ckdb_cmds[] = { { CMD_GETOPTS, "getopts", false, false, cmd_getopts, ACCESS_WEB }, { CMD_SETOPTS, "setopts", false, false, cmd_setopts, ACCESS_WEB }, { CMD_DSP, "dsp", false, false, cmd_dsp, ACCESS_SYSTEM }, - { CMD_STATS, "stats", true, false, cmd_stats, ACCESS_SYSTEM }, - { CMD_PPLNS, "pplns", false, false, cmd_pplns, ACCESS_SYSTEM }, + { CMD_STATS, "stats", true, false, cmd_stats, ACCESS_SYSTEM ACCESS_WEB }, + { CMD_PPLNS, "pplns", false, false, cmd_pplns, ACCESS_SYSTEM ACCESS_WEB }, + { CMD_USERSTATUS,"userstatus", false, false, cmd_userstatus, ACCESS_SYSTEM ACCESS_WEB }, { CMD_END, NULL, false, false, NULL, NULL } }; diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index f837e78b..c8d1d864 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -304,9 +304,10 @@ cleanup: return lastid; } -bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash, - char *newhash, char *email, char *by, char *code, - char *inet, tv_t *cd, K_TREE *trf_root) +// status was added to the end so type checking intercepts new mistakes +bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash, + char *newhash, char *email, char *by, char *code, + char *inet, tv_t *cd, K_TREE *trf_root, char *status) { ExecStatusType rescode; bool conned = false; @@ -315,7 +316,7 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash, USERS *row, *users; char *upd, *ins; bool ok = false; - char *params[5 + HISTORYDATECOUNT]; + char *params[6 + HISTORYDATECOUNT]; bool hash; int n, par = 0; @@ -337,14 +338,18 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash, DATA_USERS(row, item); memcpy(row, users, sizeof(*row)); - // Update one, leave the other + + // Update each one supplied if (hash) { // New salt each password change make_salt(row); password_hash(row->username, newhash, row->salt, row->passwordhash, sizeof(row->passwordhash)); - } else + } + if (email) STRNCPY(row->emailaddress, email); + if (status) + STRNCPY(row->status, status); HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATETRANSFER(trf_root, row); @@ -384,21 +389,22 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash, par = 0; params[par++] = bigint_to_buf(row->userid, NULL, 0); params[par++] = tv_to_buf(cd, NULL, 0); - // Copy them both in - one will be new and one will be old + // Copy them all in - at least one will be new + params[par++] = str_to_buf(row->status, NULL, 0); params[par++] = str_to_buf(row->emailaddress, NULL, 0); params[par++] = str_to_buf(row->passwordhash, NULL, 0); // New salt for each password change (or recopy old) params[par++] = str_to_buf(row->salt, NULL, 0); HISTORYDATEPARAMS(params, par, row); - PARCHKVAL(par, 5 + HISTORYDATECOUNT, params); // 10 as per ins + PARCHKVAL(par, 6 + HISTORYDATECOUNT, params); // 11 as per ins ins = "insert into users " "(userid,username,status,emailaddress,joineddate," "passwordhash,secondaryuserid,salt" HISTORYDATECONTROL ") select " - "userid,username,status,$3,joineddate," - "$4,secondaryuserid,$5," - "$6,$7,$8,$9,$10 from users where " + "userid,username,$3,$4,joineddate," + "$5,secondaryuserid,$6," + "$7,$8,$9,$10,$11 from users where " "userid=$1 and expirydate=$2"; res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE); From 180410913c14d74449824fa0007ae23680e79294 Mon Sep 17 00:00:00 2001 From: kanoi Date: Tue, 18 Nov 2014 22:51:11 +1100 Subject: [PATCH 6/9] ckdb - include workmarkers in old pplns calculations --- src/ckdb.h | 2 +- src/ckdb_cmd.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index e7341af0..57279994 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.643" +#define CKDB_VERSION DB_VERSION"-0.644" #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 53d9cbef..5d2119b9 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -2940,8 +2940,8 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in diffacc_user / diffacc_total */ -/* TODO: redesign to include workmarkers - * ... before next payout that extends into a markersummary ... */ +/* TODO: doesn't work if there are no sharesummaries, + * i.e. only markersummaries */ static char *cmd_pplns(__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, @@ -2951,8 +2951,11 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, size_t siz = sizeof(reply); K_ITEM *i_height, *i_difftimes, *i_diffadd, *i_allowaged; K_ITEM b_look, ss_look, *b_item, *w_item, *ss_item; + K_ITEM wm_look, *wm_item, ms_look, *ms_item; K_ITEM *mu_item, *wb_item, *u_item; SHARESUMMARY looksharesummary, *sharesummary; + WORKMARKERS lookworkmarkers, *workmarkers; + MARKERSUMMARY lookmarkersummary, *markersummary; MININGPAYOUTS *miningpayouts; WORKINFO *workinfo; TRANSFER *transfer; @@ -2966,7 +2969,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, int64_t share_count; char tv_buf[DATE_BUFSIZ]; tv_t cd, begin_tv, block_tv, end_tv; - K_TREE_CTX ctx[1]; + K_TREE_CTX ctx[1], wm_ctx[1], ms_ctx[1]; double ndiff, total, elapsed; double diff_times = 1.0; double diff_add = 0.0; @@ -3053,9 +3056,13 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, INIT_SHARESUMMARY(&ss_look); ss_look.data = (void *)(&looksharesummary); K_RLOCK(sharesummary_free); + K_RLOCK(workmarkers_free); + K_RLOCK(markersummary_free); ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look, cmp_sharesummary_workinfoid, ctx); if (!ss_item) { + K_RUNLOCK(markersummary_free); + K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); snprintf(reply, siz, "ERR.no shares found with or before " @@ -3071,7 +3078,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, /* add up all sharesummaries until >= diff_want * also record the latest lastshare - that will be the end pplns time * which will be >= block_tv */ - while (ss_item && total < diff_want) { + while (total < diff_want && ss_item) { switch (sharesummary->complete[0]) { case SUMMARY_CONFIRM: break; @@ -3079,6 +3086,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, if (allow_aged) break; default: + K_RUNLOCK(markersummary_free); + K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); snprintf(reply, siz, "ERR.sharesummary1 not ready in " @@ -3086,7 +3095,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, sharesummary->workinfoid); goto shazbot; } - share_count++; + share_count += sharesummary->sharecount; total += (int64_t)(sharesummary->diffacc); begin_workinfoid = sharesummary->workinfoid; if (tv_newer(&end_tv, &(sharesummary->lastshare))) @@ -3107,6 +3116,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, if (allow_aged) break; default: + K_RUNLOCK(markersummary_free); + K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); snprintf(reply, siz, "ERR.sharesummary2 not ready in " @@ -3122,6 +3133,49 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, ss_item = prev_in_ktree(ctx); DATA_SHARESUMMARY_NULL(sharesummary, ss_item); } + + /* If we haven't met or exceeded the required N, + * move on to the markersummaries */ + if (total < diff_want) { + lookworkmarkers.expirydate.tv_sec = default_expiry.tv_sec; + lookworkmarkers.expirydate.tv_usec = default_expiry.tv_usec; + lookworkmarkers.workinfoidend = begin_workinfoid; + INIT_WORKMARKERS(&wm_look); + wm_look.data = (void *)(&lookworkmarkers); + wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look, + cmp_workmarkers_workinfoid, wm_ctx); + DATA_WORKMARKERS_NULL(workmarkers, wm_item); + while (total < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) { + if (WMREADY(workmarkers->status)) { + lookmarkersummary.markerid = workmarkers->markerid; + lookmarkersummary.userid = MAXID; + lookmarkersummary.workername[0] = '\0'; + INIT_MARKERSUMMARY(&ms_look); + ms_look.data = (void *)(&lookmarkersummary); + ms_item = find_before_in_ktree(markersummary_root, &ms_look, + cmp_markersummary, ms_ctx); + DATA_MARKERSUMMARY_NULL(markersummary, ms_item); + // add the whole markerid + while (ms_item && markersummary->markerid == workmarkers->markerid) { + share_count += markersummary->sharecount; + total += (int64_t)(markersummary->diffacc); + begin_workinfoid = workmarkers->workinfoidstart; + if (tv_newer(&end_tv, &(markersummary->lastshare))) + copy_tv(&end_tv, &(markersummary->lastshare)); + mu_root = upd_add_mu(mu_root, mu_store, + markersummary->userid, + (int64_t)(markersummary->diffacc)); + ms_item = prev_in_ktree(ms_ctx); + DATA_MARKERSUMMARY_NULL(markersummary, ms_item); + } + } + wm_item = prev_in_ktree(wm_ctx); + DATA_WORKMARKERS_NULL(workmarkers, wm_item); + } + } + + K_RUNLOCK(markersummary_free); + K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); if (total == 0.0) { From b231b158e61f3bc6b84e14d511e639852ce46c5a Mon Sep 17 00:00:00 2001 From: kanoi Date: Wed, 19 Nov 2014 08:47:59 +1100 Subject: [PATCH 7/9] ckdb/php - allow pplns to show blocks that can't be or aren't ready to be paid out --- pool/page_pplns.php | 18 +++++++++- src/ckdb.c | 2 +- src/ckdb.h | 2 +- src/ckdb_cmd.c | 87 ++++++++++++++++++++++++--------------------- 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/pool/page_pplns.php b/pool/page_pplns.php index 1b46dd0e..cbd76be8 100644 --- a/pool/page_pplns.php +++ b/pool/page_pplns.php @@ -14,7 +14,7 @@ function stnum($num) return $b4.$fmt.$af; } # -# ... Of course ... check the output and add the txin +# ... Of course ... check the output and add the txin ... etc. function calctx($ans, $count, $miner_sat, $diffacc_total) { $pg = '
'; @@ -159,6 +159,7 @@ Block: $ans['miner_sat'] = $miner_sat; $data = array( 'Block' => 'block', + 'Block Status' => 'block_status', 'Block Hash' => 'block_hash', 'Block Reward (Satoshis)' => 'block_reward', 'Miner Reward (Satoshis)' => 'miner_sat', @@ -182,6 +183,21 @@ Block: $pg = '
Blockchain '.$ans['block']."
\n"; + + if (strlen($ans['block_extra']) > 0) + { + $pg .= '
'; + $msg = $ans['block_status'].' - '.$ans['block_extra']; + $pg .= str_replace(' ', ' ', $msg)."
\n"; + } + + if (strlen($ans['share_status']) > 0) + { + $pg .= '
'; + $msg = $ans['share_status']." - Can't be paid out yet"; + $pg .= str_replace(' ', ' ', $msg)."
\n"; + } + $pg .= "
\n"; $pg .= ''; $pg .= ''; diff --git a/src/ckdb.c b/src/ckdb.c index 11a0274f..8f3357b5 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1656,7 +1656,7 @@ static void summarise_blocks() if (WMREADY(workmarkers->status)) { lookmarkersummary.markerid = workmarkers->markerid; lookmarkersummary.userid = MAXID; - lookmarkersummary.workername[0] = '\0'; + lookmarkersummary.workername = EMPTY; INIT_MARKERSUMMARY(&ms_look); ms_look.data = (void *)(&lookmarkersummary); ms_item = find_before_in_ktree(markersummary_root, &ms_look, diff --git a/src/ckdb.h b/src/ckdb.h index 57279994..7767835f 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -52,7 +52,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.4" -#define CKDB_VERSION DB_VERSION"-0.644" +#define CKDB_VERSION DB_VERSION"-0.645" #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 5d2119b9..13761c58 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -2925,6 +2925,9 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in (also summarising diffacc per user) then keep stepping back until we complete the current begin_workinfoid (also summarising diffacc per user) + While we are still below diff_want + find each workmarker and add on the full set of worksummary + diffacc shares (also summarising diffacc per user) This will give us the total number of diff1 shares (diffacc_total) to use for the payment calculations The value of diff_want defaults to the block's network difficulty @@ -2938,16 +2941,18 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in diffacc_user * 2^32 / pplns_elapsed PPLNS fraction of the payout would be: diffacc_user / diffacc_total + + N.B. 'begin' means the oldest back in time and 'end' means the newest + 'end' should usually be the info of the found block with the pplns + data going back in time to 'begin' */ -/* TODO: doesn't work if there are no sharesummaries, - * i.e. only markersummaries */ static char *cmd_pplns(__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) { - char reply[1024], tmp[1024], *buf; + char reply[1024], tmp[1024], *buf, *block_extra, *share_status = EMPTY; size_t siz = sizeof(reply); K_ITEM *i_height, *i_difftimes, *i_diffadd, *i_allowaged; K_ITEM b_look, ss_look, *b_item, *w_item, *ss_item; @@ -2964,7 +2969,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, K_STORE *mu_store; USERS *users; int32_t height; - int64_t workinfoid, end_workinfoid; + int64_t workinfoid, end_workinfoid = 0; int64_t begin_workinfoid; int64_t share_count; char tv_buf[DATE_BUFSIZ]; @@ -3015,16 +3020,28 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, } DATA_BLOCKS_NULL(blocks, b_item); while (b_item && blocks->height == height) { - if (blocks->confirmed[0] == BLOCKS_CONFIRM) + // Allow any state, but report it + if (CURRENT(&(blocks->expirydate))) break; b_item = prev_in_ktree(ctx); DATA_BLOCKS_NULL(blocks, b_item); } K_RUNLOCK(blocks_free); if (!b_item || blocks->height != height) { - snprintf(reply, siz, "ERR.unconfirmed block %d", height); + snprintf(reply, siz, "ERR.no current block %d", height); return strdup(reply); } + switch (blocks->confirmed[0]) { + case BLOCKS_NEW: + block_extra = "Can't be paid out yet"; + break; + case BLOCKS_ORPHAN: + block_extra = "Can't be paid out"; + break; + default: + block_extra = EMPTY; + break; + } workinfoid = blocks->workinfoid; copy_tv(&block_tv, &(blocks->createdate)); copy_tv(&end_tv, &(blocks->createdate)); @@ -3050,6 +3067,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, share_count = 0; total = 0; + mu_store = k_new_store(miningpayouts_free); + mu_root = new_ktree(); + looksharesummary.workinfoid = workinfoid; looksharesummary.userid = MAXID; looksharesummary.workername[0] = '\0'; @@ -3060,21 +3080,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, K_RLOCK(markersummary_free); ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look, cmp_sharesummary_workinfoid, ctx); - if (!ss_item) { - K_RUNLOCK(markersummary_free); - K_RUNLOCK(workmarkers_free); - K_RUNLOCK(sharesummary_free); - snprintf(reply, siz, - "ERR.no shares found with or before " - "workinfo %"PRId64, - workinfoid); - return strdup(reply); - } - DATA_SHARESUMMARY(sharesummary, ss_item); - - mu_store = k_new_store(miningpayouts_free); - mu_root = new_ktree(); - end_workinfoid = sharesummary->workinfoid; + DATA_SHARESUMMARY_NULL(sharesummary, ss_item); + if (ss_item) + 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 >= block_tv */ @@ -3086,14 +3094,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, if (allow_aged) break; default: - K_RUNLOCK(markersummary_free); - K_RUNLOCK(workmarkers_free); - K_RUNLOCK(sharesummary_free); - snprintf(reply, siz, - "ERR.sharesummary1 not ready in " - "workinfo %"PRId64, - sharesummary->workinfoid); - goto shazbot; + share_status = "Not ready1"; } share_count += sharesummary->sharecount; total += (int64_t)(sharesummary->diffacc); @@ -3116,14 +3117,10 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, if (allow_aged) break; default: - K_RUNLOCK(markersummary_free); - K_RUNLOCK(workmarkers_free); - K_RUNLOCK(sharesummary_free); - snprintf(reply, siz, - "ERR.sharesummary2 not ready in " - "workinfo %"PRId64, - sharesummary->workinfoid); - goto shazbot; + if (share_status == EMPTY) + share_status = "Not ready2"; + else + share_status = "Not ready1+2"; } share_count++; total += (int64_t)(sharesummary->diffacc); @@ -3142,14 +3139,14 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, lookworkmarkers.workinfoidend = begin_workinfoid; INIT_WORKMARKERS(&wm_look); wm_look.data = (void *)(&lookworkmarkers); - wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look, - cmp_workmarkers_workinfoid, wm_ctx); + wm_item = find_before_in_ktree(workmarkers_root, &wm_look, + cmp_workmarkers, wm_ctx); DATA_WORKMARKERS_NULL(workmarkers, wm_item); while (total < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) { if (WMREADY(workmarkers->status)) { lookmarkersummary.markerid = workmarkers->markerid; lookmarkersummary.userid = MAXID; - lookmarkersummary.workername[0] = '\0'; + lookmarkersummary.workername = EMPTY; INIT_MARKERSUMMARY(&ms_look); ms_look.data = (void *)(&lookmarkersummary); ms_item = find_before_in_ktree(markersummary_root, &ms_look, @@ -3157,6 +3154,8 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, DATA_MARKERSUMMARY_NULL(markersummary, ms_item); // add the whole markerid while (ms_item && markersummary->markerid == workmarkers->markerid) { + if (end_workinfoid == 0) + end_workinfoid = workmarkers->workinfoidend; share_count += markersummary->sharecount; total += (int64_t)(markersummary->diffacc); begin_workinfoid = workmarkers->workinfoidstart; @@ -3173,7 +3172,6 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, DATA_WORKMARKERS_NULL(workmarkers, wm_item); } } - K_RUNLOCK(markersummary_free); K_RUNLOCK(workmarkers_free); K_RUNLOCK(sharesummary_free); @@ -3210,6 +3208,13 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "block_reward=%"PRId64"%c", blocks->reward, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "block_status=%s%c", + blocks_confirmed(blocks->confirmed), FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "block_extra=%s%c", block_extra, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "share_status=%s%c", share_status, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "workername=%s%c", blocks->workername, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); snprintf(tmp, sizeof(tmp), "nonce=%s%c", blocks->nonce, FLDSEP); From c05098f226857de07b7845966949a554905d8bb0 Mon Sep 17 00:00:00 2001 From: kanoi Date: Wed, 19 Nov 2014 10:42:07 +1100 Subject: [PATCH 8/9] php - since menu hitbox is now the full box, reduce back to 6 --- pool/page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pool/page.php b/pool/page.php index 5d0d7d44..2f335fcf 100644 --- a/pool/page.php +++ b/pool/page.php @@ -110,7 +110,7 @@ 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;} #n42 {margin:0; position: relative; color:#fff; background:#07e;} -#n42 a {color:#fff; text-decoration:none; padding: 8px; display:block;} +#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.nav {position: relative;} From 2ddfc892b4e01518b045c674428852ac2d2a3217 Mon Sep 17 00:00:00 2001 From: kanoi Date: Wed, 19 Nov 2014 11:03:35 +1100 Subject: [PATCH 9/9] php - help menu changes --- pool/prime.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pool/prime.php b/pool/prime.php index b4bd1dee..c50c69f7 100644 --- a/pool/prime.php +++ b/pool/prime.php @@ -69,8 +69,9 @@ function check() 'API' => 'api' ), 'Help' => array( - 'Help' => 'help', - 'Payouts' => 'payout' + 'Payouts' => 'payout', + 'Workers ' => 'workers', + 'Blocks' => 'blocks' ) ); tryLogInOut();
Name