Browse Source

ckdb - tidy up block update and add password change

master
kanoi 10 years ago
parent
commit
6c0850dffb
  1. 422
      src/ckdb.c

422
src/ckdb.c

@ -65,6 +65,7 @@
#define cmp_height(_cb1a, _cb1b) _cmp_height(_cb1a, _cb1b, WHERE_FFL_HERE) #define cmp_height(_cb1a, _cb1b) _cmp_height(_cb1a, _cb1b, WHERE_FFL_HERE)
static char *EMPTY = ""; static char *EMPTY = "";
static char *db_name;
static char *db_user; static char *db_user;
static char *db_pass; static char *db_pass;
@ -627,6 +628,8 @@ static const tv_t date_begin = { DATE_BEGIN, 0L };
} \ } \
} while (0) } while (0)
#define BTC_TO_D(_amt) ((double)((_amt) / 100000000.0))
// DB users,workers,auth load is complete // DB users,workers,auth load is complete
static bool db_auths_complete = false; static bool db_auths_complete = false;
// DB load is complete // DB load is complete
@ -642,7 +645,7 @@ static cklock_t fpm_lock;
static char *first_pool_message; static char *first_pool_message;
static sem_t socketer_sem; static sem_t socketer_sem;
static const char *userpatt = "^[!-~]*$"; // no spaces static const char *userpatt = "^[^/\\._ ]*$"; // disallow: '/' '.' '_'
static const char *mailpatt = "^[A-Za-z0-9_-][A-Za-z0-9_\\.-]*@[A-Za-z0-9][A-Za-z0-9\\.-]*[A-Za-z0-9]$"; static const char *mailpatt = "^[A-Za-z0-9_-][A-Za-z0-9_\\.-]*@[A-Za-z0-9][A-Za-z0-9\\.-]*[A-Za-z0-9]$";
static const char *idpatt = "^[_A-Za-z][_A-Za-z0-9]*$"; static const char *idpatt = "^[_A-Za-z][_A-Za-z0-9]*$";
static const char *intpatt = "^[0-9][0-9]*$"; static const char *intpatt = "^[0-9][0-9]*$";
@ -668,6 +671,7 @@ enum cmd_values {
CMD_SHARELOG, CMD_SHARELOG,
CMD_AUTH, CMD_AUTH,
CMD_ADDUSER, CMD_ADDUSER,
CMD_NEWPASS,
CMD_CHKPASS, CMD_CHKPASS,
CMD_POOLSTAT, CMD_POOLSTAT,
CMD_USERSTAT, CMD_USERSTAT,
@ -1060,6 +1064,10 @@ typedef struct blocks {
#define BLOCKS_NEW 'n' #define BLOCKS_NEW 'n'
#define BLOCKS_CONFIRM '1' #define BLOCKS_CONFIRM '1'
static const char *blocks_new = "New";
static const char *blocks_confirm = "1-Confirm";
static const char *blocks_unknown = "?Unknown?";
#define KANO -27972 #define KANO -27972
static K_TREE *blocks_root; static K_TREE *blocks_root;
@ -1781,7 +1789,8 @@ static PGconn *dbconnect()
PGconn *conn; PGconn *conn;
snprintf(conninfo, sizeof(conninfo), snprintf(conninfo, sizeof(conninfo),
"host=127.0.0.1 dbname=ckdb user=%s%s%s", "host=127.0.0.1 dbname=%s user=%s%s%s",
db_name,
db_user, db_pass ? " password=" : "", db_user, db_pass ? " password=" : "",
db_pass ? db_pass : ""); db_pass ? db_pass : "");
@ -2079,8 +2088,125 @@ static K_ITEM *find_userid(int64_t userid)
return find_in_ktree(userid_root, &look, cmp_userid, ctx); return find_in_ktree(userid_root, &look, cmp_userid, ctx);
} }
static bool users_add(PGconn *conn, char *username, char *emailaddress, char *passwordhash, static bool users_pass(PGconn *conn, K_ITEM *u_item, char *oldhash,
tv_t *now, char *by, char *code, char *inet) char *newhash, char *by, char *code, char *inet,
tv_t *cd, K_TREE *trf_root)
{
ExecStatusType rescode;
bool conned = false;
K_TREE_CTX ctx[1];
PGresult *res;
K_ITEM *item;
int n;
USERS *row;
char *upd, *ins;
bool ok = false;
char *params[4 + HISTORYDATECOUNT];
int par;
LOGDEBUG("%s(): change", __func__);
if (strcasecmp(oldhash, DATA_USERS(u_item)->passwordhash))
return false;
K_WLOCK(users_free);
item = k_unlink_head(users_free);
K_WUNLOCK(users_free);
row = DATA_USERS(item);
memcpy(row, DATA_USERS(u_item), sizeof(*row));
STRNCPY(row->passwordhash, newhash);
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
upd = "update users set expirydate=$1 where userid=$2 and passwordhash=$3 and expirydate=$4";
par = 0;
params[par++] = tv_to_buf(cd, NULL, 0);
params[par++] = bigint_to_buf(row->userid, NULL, 0);
params[par++] = str_to_buf(oldhash, NULL, 0);
params[par++] = tv_to_buf((tv_t *)&default_expiry, NULL, 0);
PARCHKVAL(par, 4, params);
if (conn == NULL) {
conn = dbconnect();
conned = true;
}
res = PQexec(conn, "Begin");
rescode = PQresultStatus(res);
if (!PGOK(rescode)) {
PGLOGERR("Begin", rescode, conn);
goto unparam;
}
PQclear(res);
res = PQexecParams(conn, upd, par, NULL, (const char **)params, NULL, NULL, 0);
rescode = PQresultStatus(res);
if (!PGOK(rescode)) {
PGLOGERR("Update", rescode, conn);
goto unparam;
}
for (n = 0; n < par; n++)
free(params[n]);
par = 0;
params[par++] = bigint_to_buf(row->userid, NULL, 0);
params[par++] = tv_to_buf(cd, NULL, 0);
params[par++] = str_to_buf(row->passwordhash, NULL, 0);
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 3 + HISTORYDATECOUNT, params); // 8 as per ins
ins = "insert into users "
"(userid,username,emailaddress,joineddate,passwordhash,"
"secondaryuserid"
HISTORYDATECONTROL ") select "
"userid,username,emailaddress,joineddate,$3,"
"secondaryuserid,"
"$4,$5,$6,$7,$8 from users where "
"userid=$1 and expirydate=$2";
res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0);
rescode = PQresultStatus(res);
PQclear(res);
if (!PGOK(rescode)) {
PGLOGERR("Insert", rescode, conn);
res = PQexec(conn, "Rollback");
goto unparam;
}
res = PQexec(conn, "Commit");
ok = true;
unparam:
PQclear(res);
if (conned)
PQfinish(conn);
for (n = 0; n < par; n++)
free(params[n]);
K_WLOCK(users_free);
if (!ok)
k_add_head(users_free, item);
else {
users_root = remove_from_ktree(users_root, u_item, cmp_users, ctx);
userid_root = remove_from_ktree(userid_root, u_item, cmp_userid, ctx);
copy_tv(&(DATA_USERS(u_item)->expirydate), cd);
users_root = add_to_ktree(users_root, u_item, cmp_users);
userid_root = add_to_ktree(userid_root, u_item, cmp_userid);
users_root = add_to_ktree(users_root, item, cmp_users);
userid_root = add_to_ktree(userid_root, item, cmp_userid);
k_add_head(users_store, item);
}
K_WUNLOCK(users_free);
return ok;
}
static bool users_add(PGconn *conn, char *username, char *emailaddress,
char *passwordhash, char *by, char *code, char *inet,
tv_t *cd, K_TREE *trf_root)
{ {
ExecStatusType rescode; ExecStatusType rescode;
bool conned = false; bool conned = false;
@ -2105,7 +2231,7 @@ static bool users_add(PGconn *conn, char *username, char *emailaddress, char *pa
row = DATA_USERS(item); row = DATA_USERS(item);
row->userid = nextid(conn, "userid", (int64_t)(666 + (rand() % 334)), row->userid = nextid(conn, "userid", (int64_t)(666 + (rand() % 334)),
now, by, code, inet); cd, by, code, inet);
if (row->userid == 0) if (row->userid == 0)
goto unitem; goto unitem;
@ -2119,7 +2245,8 @@ static bool users_add(PGconn *conn, char *username, char *emailaddress, char *pa
HASH_BER(tohash, strlen(tohash), 1, hash, tmp); HASH_BER(tohash, strlen(tohash), 1, hash, tmp);
__bin2hex(row->secondaryuserid, (void *)(&hash), sizeof(hash)); __bin2hex(row->secondaryuserid, (void *)(&hash), sizeof(hash));
HISTORYDATEINIT(row, now, by, code, inet); HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
// copy createdate // copy createdate
row->joineddate.tv_sec = row->createdate.tv_sec; row->joineddate.tv_sec = row->createdate.tv_sec;
@ -2317,7 +2444,7 @@ static K_ITEM *find_workers(int64_t userid, char *workername)
static K_ITEM *workers_add(PGconn *conn, int64_t userid, char *workername, static K_ITEM *workers_add(PGconn *conn, int64_t userid, char *workername,
char *difficultydefault, char *idlenotificationenabled, char *difficultydefault, char *idlenotificationenabled,
char *idlenotificationtime, char *by, char *idlenotificationtime, char *by,
char *code, char *inet, tv_t *cd) char *code, char *inet, tv_t *cd, K_TREE *trf_root)
{ {
ExecStatusType rescode; ExecStatusType rescode;
bool conned = false; bool conned = false;
@ -2381,6 +2508,7 @@ static K_ITEM *workers_add(PGconn *conn, int64_t userid, char *workername,
row->idlenotificationtime = IDLENOTIFICATIONTIME_DEF; row->idlenotificationtime = IDLENOTIFICATIONTIME_DEF;
HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
par = 0; par = 0;
params[par++] = bigint_to_buf(row->workerid, NULL, 0); params[par++] = bigint_to_buf(row->workerid, NULL, 0);
@ -2426,7 +2554,7 @@ unitem:
static bool workers_update(PGconn *conn, K_ITEM *item, char *difficultydefault, static bool workers_update(PGconn *conn, K_ITEM *item, char *difficultydefault,
char *idlenotificationenabled, char *idlenotificationtime, char *idlenotificationenabled, char *idlenotificationtime,
char *by, char *code, char *inet, tv_t *cd) char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root)
{ {
ExecStatusType rescode; ExecStatusType rescode;
bool conned = false; bool conned = false;
@ -2472,6 +2600,7 @@ static bool workers_update(PGconn *conn, K_ITEM *item, char *difficultydefault,
nottime = row->idlenotificationtime; nottime = row->idlenotificationtime;
HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
if (diffdef == row->difficultydefault && if (diffdef == row->difficultydefault &&
idlenot == row->idlenotificationenabled[0] && idlenot == row->idlenotificationenabled[0] &&
@ -2557,7 +2686,7 @@ early:
static K_ITEM *new_worker(PGconn *conn, bool update, int64_t userid, char *workername, static K_ITEM *new_worker(PGconn *conn, bool update, int64_t userid, char *workername,
char *diffdef, char *idlenotificationenabled, char *diffdef, char *idlenotificationenabled,
char *idlenotificationtime, char *by, char *idlenotificationtime, char *by,
char *code, char *inet, tv_t *cd) char *code, char *inet, tv_t *cd, K_TREE *trf_root)
{ {
K_ITEM *item; K_ITEM *item;
@ -2565,19 +2694,20 @@ static K_ITEM *new_worker(PGconn *conn, bool update, int64_t userid, char *worke
if (item) { if (item) {
if (update) { if (update) {
workers_update(conn, item, diffdef, idlenotificationenabled, workers_update(conn, item, diffdef, idlenotificationenabled,
idlenotificationtime, by, code, inet, cd); idlenotificationtime, by, code, inet, cd,
trf_root);
} }
} else { } else {
// TODO: limit how many? // TODO: limit how many?
item = workers_add(conn, userid, workername, diffdef, item = workers_add(conn, userid, workername, diffdef,
idlenotificationenabled, idlenotificationtime, idlenotificationenabled, idlenotificationtime,
by, code, inet, cd); by, code, inet, cd, trf_root);
} }
return item; return item;
} }
static K_ITEM *new_default_worker(PGconn *conn, bool update, int64_t userid, char *workername, static K_ITEM *new_default_worker(PGconn *conn, bool update, int64_t userid, char *workername,
char *by, char *code, char *inet, tv_t *cd) char *by, char *code, char *inet, tv_t *cd, K_TREE *trf_root)
{ {
bool conned = false; bool conned = false;
K_ITEM *item; K_ITEM *item;
@ -2589,7 +2719,7 @@ static K_ITEM *new_default_worker(PGconn *conn, bool update, int64_t userid, cha
item = new_worker(conn, update, userid, workername, DIFFICULTYDEFAULT_DEF_STR, item = new_worker(conn, update, userid, workername, DIFFICULTYDEFAULT_DEF_STR,
IDLENOTIFICATIONENABLED_DEF, IDLENOTIFICATIONTIME_DEF_STR, IDLENOTIFICATIONENABLED_DEF, IDLENOTIFICATIONTIME_DEF_STR,
by, code, inet, cd); by, code, inet, cd, trf_root);
if (conned) if (conned)
PQfinish(conn); PQfinish(conn);
@ -2601,8 +2731,9 @@ static K_ITEM *new_default_worker(PGconn *conn, bool update, int64_t userid, cha
static K_ITEM *new_worker_find_user(PGconn *conn, bool update, char *username, static K_ITEM *new_worker_find_user(PGconn *conn, bool update, char *username,
char *workername, char *diffdef, char *workername, char *diffdef,
char *idlenotificationenabled, char *idlenotificationenabled,
char *idlenotificationtime, tv_t *now, char *idlenotificationtime,
char *by, char *code, char *inet) char *by, char *code, char *inet,
tv_t *cd, K_TREE *trf_root)
{ {
K_ITEM *item; K_ITEM *item;
@ -2614,7 +2745,7 @@ static K_ITEM *new_worker_find_user(PGconn *conn, bool update, char *username,
return new_worker(conn, update, DATA_USERS(item)->userid, workername, return new_worker(conn, update, DATA_USERS(item)->userid, workername,
diffdef, idlenotificationenabled, diffdef, idlenotificationenabled,
idlenotificationtime, now, by, code, inet); idlenotificationtime, by, code, inet, cd, trf_root);
} }
*/ */
@ -3426,7 +3557,7 @@ static bool shares_add(PGconn *conn, char *workinfoid, char *username, char *wor
goto unitem; goto unitem;
w_item = new_default_worker(conn, false, shares->userid, shares->workername, w_item = new_default_worker(conn, false, shares->userid, shares->workername,
by, code, inet, cd); by, code, inet, cd, trf_root);
if (!w_item) if (!w_item)
goto unitem; goto unitem;
@ -3536,7 +3667,7 @@ static bool shareerrors_add(PGconn *conn, char *workinfoid, char *username,
goto unitem; goto unitem;
w_item = new_default_worker(NULL, false, shareerrors->userid, shareerrors->workername, w_item = new_default_worker(NULL, false, shareerrors->userid, shareerrors->workername,
by, code, inet, cd); by, code, inet, cd, trf_root);
if (!w_item) if (!w_item)
goto unitem; goto unitem;
@ -4118,7 +4249,7 @@ void sharesummary_reload()
PQfinish(conn); PQfinish(conn);
} }
// order by height asc,blockhash asc,expirydate asc // order by height asc,blockhash asc,expirydate desc
static cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b) static cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b)
{ {
cmp_t c = CMP_INT(DATA_BLOCKS(a)->height, cmp_t c = CMP_INT(DATA_BLOCKS(a)->height,
@ -4127,14 +4258,14 @@ static cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b)
c = CMP_STR(DATA_BLOCKS(a)->blockhash, c = CMP_STR(DATA_BLOCKS(a)->blockhash,
DATA_BLOCKS(b)->blockhash); DATA_BLOCKS(b)->blockhash);
if (c == 0) { if (c == 0) {
c = CMP_TV(DATA_BLOCKS(a)->expirydate, c = CMP_TV(DATA_BLOCKS(b)->expirydate,
DATA_BLOCKS(b)->expirydate); DATA_BLOCKS(a)->expirydate);
} }
} }
return c; return c;
} }
/* unused // Must be R or W locked before call - gets current status (default_expiry)
static K_ITEM *find_blocks(int32_t height, char *blockhash) static K_ITEM *find_blocks(int32_t height, char *blockhash)
{ {
BLOCKS blocks; BLOCKS blocks;
@ -4149,8 +4280,19 @@ static K_ITEM *find_blocks(int32_t height, char *blockhash)
look.data = (void *)(&blocks); look.data = (void *)(&blocks);
return find_in_ktree(blocks_root, &look, cmp_blocks, ctx); return find_in_ktree(blocks_root, &look, cmp_blocks, ctx);
} }
*/
static const char *blocks_confirmed(char *confirmed)
{
switch (confirmed[0]) {
case BLOCKS_NEW:
return blocks_new;
case BLOCKS_CONFIRM:
return blocks_confirm;
}
return blocks_unknown;
}
// TODO: determine how to handle orphan blocks after 1 confirm
static bool blocks_add(PGconn *conn, char *height, char *blockhash, static bool blocks_add(PGconn *conn, char *height, char *blockhash,
char *confirmed, char *workinfoid, char *username, char *confirmed, char *workinfoid, char *username,
char *workername, char *clientid, char *enonce1, char *workername, char *clientid, char *enonce1,
@ -4162,30 +4304,57 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
bool conned = false; bool conned = false;
PGresult *res = NULL; PGresult *res = NULL;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
K_ITEM *item, *u_item; K_ITEM *b_item, *u_item, *old_b_item;
char cd_buf[DATE_BUFSIZ];
char blk_dsp[16+1], *ptr;
BLOCKS *row; BLOCKS *row;
char *upd, *ins; char *upd, *ins;
char *params[11 + HISTORYDATECOUNT]; char *params[11 + HISTORYDATECOUNT];
bool ok = false; bool ok = false, update_old = false;
int par = 0; int par = 0;
int n; int n;
LOGDEBUG("%s(): add", __func__); LOGDEBUG("%s(): add", __func__);
K_WLOCK(blocks_free); K_WLOCK(blocks_free);
item = k_unlink_head(blocks_free); b_item = k_unlink_head(blocks_free);
K_WUNLOCK(blocks_free); K_WUNLOCK(blocks_free);
row = DATA_BLOCKS(item); row = DATA_BLOCKS(b_item);
TXT_TO_INT("height", height, row->height); TXT_TO_INT("height", height, row->height);
STRNCPY(row->blockhash, blockhash); STRNCPY(row->blockhash, blockhash);
STRNCPY(row->confirmed, confirmed);
HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATEINIT(row, cd, by, code, inet);
// TODO: do this better ... :)
ptr = blockhash + strlen(blockhash) - (sizeof(blk_dsp)-1) - 8;
if (ptr < blockhash)
ptr = blockhash;
STRNCPY(blk_dsp, ptr);
K_WLOCK(blocks_free);
old_b_item = find_blocks(row->height, blockhash);
switch (confirmed[0]) { switch (confirmed[0]) {
case BLOCKS_NEW: case BLOCKS_NEW:
// None should exist - so must be a duplicate
if (old_b_item) {
k_add_head(blocks_free, b_item);
K_WUNLOCK(blocks_free);
if (!igndup) {
tv_to_buf(cd, cd_buf, sizeof(cd_buf));
LOGERR("%s(): Duplicate (%s) blocks ignored, Status: "
"%s, Block: %s/...%s/%s",
__func__,
blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed),
blocks_confirmed(confirmed),
height, blk_dsp, cd_buf);
}
return true;
}
K_WUNLOCK(blocks_free);
K_RLOCK(users_free); K_RLOCK(users_free);
u_item = find_users(username); u_item = find_users(username);
K_RUNLOCK(users_free); K_RUNLOCK(users_free);
@ -4194,6 +4363,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
else else
row->userid = DATA_USERS(u_item)->userid; row->userid = DATA_USERS(u_item)->userid;
STRNCPY(row->confirmed, confirmed);
TXT_TO_BIGINT("workinfoid", workinfoid, row->workinfoid); TXT_TO_BIGINT("workinfoid", workinfoid, row->workinfoid);
STRNCPY(row->workername, workername); STRNCPY(row->workername, workername);
TXT_TO_INT("clientid", clientid, row->clientid); TXT_TO_INT("clientid", clientid, row->clientid);
@ -4204,13 +4374,6 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
HISTORYDATETRANSFER(trf_root, row); HISTORYDATETRANSFER(trf_root, row);
if (igndup && find_in_ktree(blocks_root, item, cmp_blocks, ctx)) {
K_WLOCK(blocks_free);
k_add_head(blocks_free, item);
K_WUNLOCK(blocks_free);
return true;
}
par = 0; par = 0;
params[par++] = int_to_buf(row->height, NULL, 0); params[par++] = int_to_buf(row->height, NULL, 0);
params[par++] = str_to_buf(row->blockhash, NULL, 0); params[par++] = str_to_buf(row->blockhash, NULL, 0);
@ -4244,7 +4407,34 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
} }
break; break;
case BLOCKS_CONFIRM: case BLOCKS_CONFIRM:
// TODO: ignore a duplicate if igndup if (!old_b_item) {
k_add_head(blocks_free, b_item);
K_WUNLOCK(blocks_free);
tv_to_buf(cd, cd_buf, sizeof(cd_buf));
LOGERR("%s(): Can't confirm a non-existent block, Status: "
"%s, Block: %s/...%s/%s",
__func__, blocks_confirmed(confirmed),
height, blk_dsp, cd_buf);
return false;
}
/* This will also treat an unrecognised 'confirmed' as a
* duplicate since they shouldn't exist anyway */
if (DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_NEW) {
k_add_head(blocks_free, b_item);
K_WUNLOCK(blocks_free);
if (!igndup || DATA_BLOCKS(old_b_item)->confirmed[0] != BLOCKS_CONFIRM) {
tv_to_buf(cd, cd_buf, sizeof(cd_buf));
LOGERR("%s(): Duplicate (%s) blocks ignored, Status: "
"%s, Block: %s/...%s/%s",
__func__,
blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed),
blocks_confirmed(confirmed),
height, blk_dsp, cd_buf);
}
return true;
}
K_WUNLOCK(blocks_free);
upd = "update blocks set expirydate=$1 where blockhash=$2 and expirydate=$3"; upd = "update blocks set expirydate=$1 where blockhash=$2 and expirydate=$3";
par = 0; par = 0;
params[par++] = tv_to_buf(cd, NULL, 0); params[par++] = tv_to_buf(cd, NULL, 0);
@ -4257,6 +4447,18 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
conned = true; conned = true;
} }
STRNCPY(row->confirmed, confirmed);
// New is mostly a copy of the old
row->workinfoid = DATA_BLOCKS(old_b_item)->workinfoid;
STRNCPY(row->workername, DATA_BLOCKS(old_b_item)->workername);
row->clientid = DATA_BLOCKS(old_b_item)->clientid;
STRNCPY(row->enonce1, DATA_BLOCKS(old_b_item)->enonce1);
STRNCPY(row->nonce2, DATA_BLOCKS(old_b_item)->nonce2);
STRNCPY(row->nonce, DATA_BLOCKS(old_b_item)->nonce);
row->reward = DATA_BLOCKS(old_b_item)->reward;
HISTORYDATETRANSFER(trf_root, row);
res = PQexec(conn, "Begin"); res = PQexec(conn, "Begin");
rescode = PQresultStatus(res); rescode = PQresultStatus(res);
if (!PGOK(rescode)) { if (!PGOK(rescode)) {
@ -4302,9 +4504,12 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash,
goto unparam; goto unparam;
} }
update_old = true;
res = PQexec(conn, "Commit"); res = PQexec(conn, "Commit");
break; break;
default: default:
K_WUNLOCK(blocks_free);
LOGERR("%s(): %s.failed.invalid confirm='%s'", LOGERR("%s(): %s.failed.invalid confirm='%s'",
__func__, id, confirmed); __func__, id, confirmed);
goto flail; goto flail;
@ -4321,13 +4526,36 @@ flail:
K_WLOCK(blocks_free); K_WLOCK(blocks_free);
if (!ok) if (!ok)
k_add_head(blocks_free, item); k_add_head(blocks_free, b_item);
else { else {
blocks_root = add_to_ktree(blocks_root, item, cmp_blocks); if (update_old) {
k_add_head(blocks_store, item); blocks_root = remove_from_ktree(blocks_root, old_b_item, cmp_blocks, ctx);
copy_tv(&(DATA_BLOCKS(old_b_item)->expirydate), cd);
blocks_root = add_to_ktree(blocks_root, old_b_item, cmp_blocks);
}
blocks_root = add_to_ktree(blocks_root, b_item, cmp_blocks);
k_add_head(blocks_store, b_item);
} }
K_WUNLOCK(blocks_free); K_WUNLOCK(blocks_free);
if (ok) {
char tmp[128];
if (confirmed[0] != BLOCKS_NEW)
tmp[0] = '\0';
else {
snprintf(tmp, sizeof(tmp),
" Reward: %f, User: %s, Worker: %s",
BTC_TO_D(DATA_BLOCKS(b_item)->reward),
username, workername);
}
LOGWARNING("%s(): BLOCK! Status: %s, Block: %s/...%s%s",
__func__,
blocks_confirmed(confirmed),
height, blk_dsp, tmp);
}
return ok; return ok;
} }
@ -4338,8 +4566,6 @@ static bool blocks_fill(PGconn *conn)
K_ITEM *item; K_ITEM *item;
int n, i; int n, i;
BLOCKS *row; BLOCKS *row;
char *params[1];
int par;
char *field; char *field;
char *sel; char *sel;
int fields = 11; int fields = 11;
@ -4351,11 +4577,8 @@ static bool blocks_fill(PGconn *conn)
"height,blockhash,workinfoid,userid,workername," "height,blockhash,workinfoid,userid,workername,"
"clientid,enonce1,nonce2,nonce,reward,confirmed" "clientid,enonce1,nonce2,nonce,reward,confirmed"
HISTORYDATECONTROL HISTORYDATECONTROL
" from blocks where expirydate=$1"; " from blocks";
par = 0; res = PQexec(conn, sel);
params[par++] = tv_to_buf((tv_t *)(&default_expiry), NULL, 0);
PARCHK(par, params);
res = PQexecParams(conn, sel, par, NULL, (const char **)params, NULL, NULL, 0);
rescode = PQresultStatus(res); rescode = PQresultStatus(res);
if (!PGOK(rescode)) { if (!PGOK(rescode)) {
PGLOGERR("Select", rescode, conn); PGLOGERR("Select", rescode, conn);
@ -4529,7 +4752,7 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username,
// since update=false, a dup will be ok and do nothing when igndup=true // since update=false, a dup will be ok and do nothing when igndup=true
new_worker(conn, false, row->userid, workername, DIFFICULTYDEFAULT_DEF_STR, new_worker(conn, false, row->userid, workername, DIFFICULTYDEFAULT_DEF_STR,
IDLENOTIFICATIONENABLED_DEF, IDLENOTIFICATIONTIME_DEF_STR, IDLENOTIFICATIONENABLED_DEF, IDLENOTIFICATIONTIME_DEF_STR,
by, code, inet, cd); by, code, inet, cd, trf_root);
STRNCPY(row->workername, workername); STRNCPY(row->workername, workername);
TXT_TO_INT("clientid", clientid, row->clientid); TXT_TO_INT("clientid", clientid, row->clientid);
STRNCPY(row->enonce1, enonce1); STRNCPY(row->enonce1, enonce1);
@ -5876,7 +6099,7 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by,
ok = users_add(conn, DATA_TRANSFER(i_username)->data, ok = users_add(conn, DATA_TRANSFER(i_username)->data,
DATA_TRANSFER(i_emailaddress)->data, DATA_TRANSFER(i_emailaddress)->data,
DATA_TRANSFER(i_passwordhash)->data, DATA_TRANSFER(i_passwordhash)->data,
now, by, code, inet); by, code, inet, now, trf_root);
if (!ok) { if (!ok) {
LOGERR("%s.failed.DBE", id); LOGERR("%s.failed.DBE", id);
@ -5887,6 +6110,48 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by,
return strdup(reply); return strdup(reply);
} }
static char *cmd_newpass(__maybe_unused PGconn *conn, char *cmd, char *id,
tv_t *now, char *by, char *code, char *inet,
__maybe_unused tv_t *cd, K_TREE *trf_root)
{
K_ITEM *i_username, *i_oldhash, *i_newhash, *u_item;
char reply[1024] = "";
size_t siz = sizeof(reply);
bool ok = false;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
i_username = require_name(trf_root, "username", 3, (char *)userpatt, reply, siz);
if (!i_username)
return strdup(reply);
i_oldhash = require_name(trf_root, "oldhash", 64, (char *)hashpatt, reply, siz);
if (!i_oldhash)
return strdup(reply);
i_newhash = require_name(trf_root, "newhash", 64, (char *)hashpatt, reply, siz);
if (!i_newhash)
return strdup(reply);
K_RLOCK(users_free);
u_item = find_users(DATA_TRANSFER(i_username)->data);
K_RUNLOCK(users_free);
if (u_item) {
ok = users_pass(NULL, u_item,
DATA_TRANSFER(i_oldhash)->data,
DATA_TRANSFER(i_newhash)->data,
by, code, inet, now, trf_root);
}
if (!ok) {
LOGERR("%s.failed.%s", id, DATA_TRANSFER(i_username)->data);
return strdup("failed.");
}
LOGDEBUG("%s.ok.%s", id, DATA_TRANSFER(i_username)->data);
return strdup("ok.");
}
static char *cmd_chkpass(__maybe_unused PGconn *conn, char *cmd, char *id, static char *cmd_chkpass(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused tv_t *now, __maybe_unused char *by, __maybe_unused tv_t *now, __maybe_unused char *by,
__maybe_unused char *code, __maybe_unused char *inet, __maybe_unused char *code, __maybe_unused char *inet,
@ -7203,6 +7468,7 @@ static struct CMDS {
{ CMD_SHARELOG, STR_AGEWORKINFO, false, true, cmd_sharelog, ACCESS_POOL }, { CMD_SHARELOG, STR_AGEWORKINFO, false, true, cmd_sharelog, ACCESS_POOL },
{ CMD_AUTH, "authorise", false, true, cmd_auth, ACCESS_POOL }, { CMD_AUTH, "authorise", false, true, cmd_auth, ACCESS_POOL },
{ CMD_ADDUSER, "adduser", false, false, cmd_adduser, ACCESS_WEB }, { CMD_ADDUSER, "adduser", false, false, cmd_adduser, ACCESS_WEB },
{ CMD_NEWPASS, "newpass", false, false, cmd_newpass, ACCESS_WEB },
{ CMD_CHKPASS, "chkpass", false, false, cmd_chkpass, ACCESS_WEB }, { CMD_CHKPASS, "chkpass", false, false, cmd_chkpass, ACCESS_WEB },
{ CMD_POOLSTAT, "poolstats", false, true, cmd_poolstats, ACCESS_POOL }, { CMD_POOLSTAT, "poolstats", false, true, cmd_poolstats, ACCESS_POOL },
{ CMD_USERSTAT, "userstats", false, true, cmd_userstats, ACCESS_POOL }, { CMD_USERSTAT, "userstats", false, true, cmd_userstats, ACCESS_POOL },
@ -7643,8 +7909,9 @@ static void *socketer(__maybe_unused void *arg)
char *end, *ans = NULL, *rep = NULL, *buf = NULL, *dot; char *end, *ans = NULL, *rep = NULL, *buf = NULL, *dot;
char cmd[CMD_SIZ+1], id[ID_SIZ+1], reply[1024+1]; char cmd[CMD_SIZ+1], id[ID_SIZ+1], reply[1024+1];
char *last_auth = NULL, *reply_auth = NULL; char *last_auth = NULL, *reply_auth = NULL;
char *last_adduser = NULL, *reply_adduser = NULL;
char *last_chkpass = NULL, *reply_chkpass = NULL; char *last_chkpass = NULL, *reply_chkpass = NULL;
char *last_adduser = NULL, *reply_adduser = NULL;
char *last_newpass = NULL, *reply_newpass = NULL;
char *last_newid = NULL, *reply_newid = NULL; char *last_newid = NULL, *reply_newid = NULL;
char *last_web = NULL, *reply_web = NULL; char *last_web = NULL, *reply_web = NULL;
char *reply_last, duptype[CMD_SIZ+1]; char *reply_last, duptype[CMD_SIZ+1];
@ -7711,9 +7978,9 @@ static void *socketer(__maybe_unused void *arg)
* will effectively reduce the processing load for * will effectively reduce the processing load for
* sequential duplicates * sequential duplicates
* adduser duplicates are handled by the DB code * adduser duplicates are handled by the DB code
* auth, chkpass, adduser, newid - remember individual * auth, chkpass, adduser, newpass, newid -
* last message and reply and repeat the reply without * remember individual last message and reply and repeat
* reprocessing the message * the reply without reprocessing the message
*/ */
dup = false; dup = false;
if (last_auth && strcmp(last_auth, buf) == 0) { if (last_auth && strcmp(last_auth, buf) == 0) {
@ -7725,6 +7992,9 @@ static void *socketer(__maybe_unused void *arg)
} else if (last_adduser && strcmp(last_adduser, buf) == 0) { } else if (last_adduser && strcmp(last_adduser, buf) == 0) {
reply_last = reply_adduser; reply_last = reply_adduser;
dup = true; dup = true;
} else if (last_newpass && strcmp(last_newpass, buf) == 0) {
reply_last = reply_newpass;
dup = true;
} else if (last_newid && strcmp(last_newid, buf) == 0) { } else if (last_newid && strcmp(last_newid, buf) == 0) {
reply_last = reply_newid; reply_last = reply_newid;
dup = true; dup = true;
@ -7765,6 +8035,7 @@ static void *socketer(__maybe_unused void *arg)
case CMD_AUTH: case CMD_AUTH:
case CMD_CHKPASS: case CMD_CHKPASS:
case CMD_ADDUSER: case CMD_ADDUSER:
case CMD_NEWPASS:
case CMD_NEWID: case CMD_NEWID:
case CMD_STATS: case CMD_STATS:
ans = cmds[which_cmds].func(NULL, cmd, id, &now, ans = cmds[which_cmds].func(NULL, cmd, id, &now,
@ -7806,6 +8077,15 @@ static void *socketer(__maybe_unused void *arg)
free(reply_adduser); free(reply_adduser);
reply_adduser = rep; reply_adduser = rep;
break; break;
case CMD_NEWPASS:
if (last_newpass)
free(last_newpass);
last_newpass = buf;
buf = NULL;
if (reply_newpass)
free(reply_newpass);
reply_newpass = rep;
break;
case CMD_NEWID: case CMD_NEWID:
if (last_newid) if (last_newid)
free(last_newid); free(last_newid);
@ -7981,6 +8261,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
case CMD_PING: case CMD_PING:
// Non pool commands, shouldn't be there // Non pool commands, shouldn't be there
case CMD_ADDUSER: case CMD_ADDUSER:
case CMD_NEWPASS:
case CMD_CHKPASS: case CMD_CHKPASS:
case CMD_NEWID: case CMD_NEWID:
case CMD_PAYMENTS: case CMD_PAYMENTS:
@ -8035,12 +8316,13 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
// Log files are every ... // Log files are every ...
#define ROLL_S 3600 #define ROLL_S 3600
// 10Mb for now // 10Mb for now - transactiontree can be large
#define MAX_READ (10 * 1024 * 1024) #define MAX_READ (10 * 1024 * 1024)
static char *reload_buf;
/* If the reload start file is missing and -r was specified correctly: /* If the reload start file is missing and -r was specified correctly:
* touch the filename reported in "Failed to open 'filename'" * touch the filename reported in "Failed to open 'filename'"
* when ckdb aborts at the beginning of the reload */ * if ckdb aborts at the beginning of the reload, then start again */
static bool reload_from(tv_t *start) static bool reload_from(tv_t *start)
{ {
PGconn *conn = NULL; PGconn *conn = NULL;
@ -8051,11 +8333,14 @@ static bool reload_from(tv_t *start)
int processing; int processing;
bool finished = false, matched = false, ret = true; bool finished = false, matched = false, ret = true;
char *filename = NULL; char *filename = NULL;
char data[MAX_READ];
uint64_t count, total; uint64_t count, total;
tv_t now; tv_t now;
FILE *fp = NULL; FILE *fp = NULL;
reload_buf = malloc(MAX_READ);
if (!reload_buf)
quithere(1, "OOM");
reloading = true; reloading = true;
tv_to_buf(start, buf, sizeof(buf)); tv_to_buf(start, buf, sizeof(buf));
@ -8068,8 +8353,8 @@ static bool reload_from(tv_t *start)
setnow(&now); setnow(&now);
tvs_to_buf(&now, run, sizeof(run)); tvs_to_buf(&now, run, sizeof(run));
snprintf(data, sizeof(data), "reload.%s.s0", run); snprintf(reload_buf, MAX_READ, "reload.%s.s0", run);
LOGFILE(data); LOGFILE(reload_buf);
conn = dbconnect(); conn = dbconnect();
@ -8080,8 +8365,8 @@ static bool reload_from(tv_t *start)
processing++; processing++;
count = 0; count = 0;
while (!matched && fgets_unlocked(data, MAX_READ, fp)) while (!matched && fgets_unlocked(reload_buf, MAX_READ, fp))
matched = reload_line(conn, filename, ++count, data); matched = reload_line(conn, filename, ++count, reload_buf);
if (ferror(fp)) { if (ferror(fp)) {
int err = errno; int err = errno;
@ -8146,8 +8431,8 @@ static bool reload_from(tv_t *start)
PQfinish(conn); PQfinish(conn);
snprintf(data, sizeof(data), "reload.%s.%"PRIu64, run, total); snprintf(reload_buf, MAX_READ, "reload.%s.%"PRIu64, run, total);
LOGFILE(data); LOGFILE(reload_buf);
LOGWARNING("%s(): read %d file%s, total %"PRIu64" line%s", LOGWARNING("%s(): read %d file%s, total %"PRIu64" line%s",
__func__, __func__,
processing, processing == 1 ? "" : "s", processing, processing == 1 ? "" : "s",
@ -8166,6 +8451,9 @@ static bool reload_from(tv_t *start)
reloading = false; reloading = false;
free(reload_buf);
reload_buf = NULL;
return ret; return ret;
} }
@ -8294,10 +8582,16 @@ int main(int argc, char **argv)
memset(&ckp, 0, sizeof(ckp)); memset(&ckp, 0, sizeof(ckp));
ckp.loglevel = LOG_NOTICE; ckp.loglevel = LOG_NOTICE;
while ((c = getopt(argc, argv, "c:kl:n:p:r:s:u:")) != -1) { while ((c = getopt(argc, argv, "c:d:kl:n:p:r:s:u:")) != -1) {
switch(c) { switch(c) {
case 'c': case 'c':
ckp.config = optarg; ckp.config = strdup(optarg);
break;
case 'd':
db_name = strdup(optarg);
kill = optarg;
while (*kill)
*(kill++) = ' ';
break; break;
case 'k': case 'k':
ckp.killold = true; ckp.killold = true;
@ -8337,6 +8631,8 @@ int main(int argc, char **argv)
check_restore_dir(); check_restore_dir();
if (!db_name)
db_name = "ckdb";
if (!db_user) if (!db_user)
db_user = "postgres"; db_user = "postgres";
if (!ckp.name) if (!ckp.name)

Loading…
Cancel
Save