From be97523bfced58f4496840fcc20bf8a084dc32dd Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 13:01:46 +1000 Subject: [PATCH 01/14] ckdb - update code docs/TODOs --- src/ckdb.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 769577e1..ea3c723e 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1043,7 +1043,7 @@ static K_LIST *optioncontrol_free; static K_STORE *optioncontrol_store; */ -// TODO: aging/discarding workinfo,shares +// TODO: discarding workinfo,shares // WORKINFO workinfo.id.json={...} typedef struct workinfo { int64_t workinfoid; @@ -3158,7 +3158,7 @@ static bool payments_fill(PGconn *conn) LOGDEBUG("%s(): select", __func__); - // TODO: handle selecting a subset, eg 20 per web page + // TODO: handle selecting a subset, eg 20 per web page (in blocklist also) sel = "select " "userid,paydate,payaddress,originaltxn,amount,committxn,commitblockhash" HISTORYDATECONTROL @@ -3481,20 +3481,6 @@ static bool _sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row static cmp_t cmp_sharesummary_workinfoid(K_ITEM *a, K_ITEM *b); static cmp_t cmp_shares(K_ITEM *a, K_ITEM *b); -/* N.B. a DB check can be done to find sharesummaries that have missed being - * aged (and a possible problem with the aging process): - * e.g. for a date D in the past of at least a few hours - * select count(*) from sharesummary where createdate<'D' and complete='n'; - * and can be easily corrected: - * update sharesummary set complete='a' where createdate<'D' and complete='n'; - * It's important to make sure the D value is far enough in the past such that - * all the matching sharesummary records in ckdb have certainly completed - * ckdb would need to restart to get the updated DB information though it would - * not affect current ckdb code - * TODO: This will happen until auto aging is added here - since ckpool can not reliably - * age all workinfo that was active when it exits (e.g. a crash) so best to not - * try, but get ckdb to auto age old unaged data - */ static bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance, char *by, char *code, char *inet, tv_t *cd, tv_t *ss_first, tv_t *ss_last, int64_t *ss_count, @@ -4097,9 +4083,6 @@ unitem: static bool shares_fill() { - // TODO: reload shares from workinfo from log file - // and verify workinfo while doing that - return true; } @@ -4234,9 +4217,6 @@ unitem: static bool shareerrors_fill() { - // TODO: reload shareerrors from workinfo from log file - // and verify workinfo while doing that - return true; } @@ -5704,7 +5684,7 @@ static bool auths_fill(PGconn *conn) LOGDEBUG("%s(): select", __func__); - // TODO: keep last x - since a user may login and mine for 100 days + // TODO: add/update a (single) fake auth every ~10min or 10min after the last one? sel = "select " "authid,userid,workername,clientid,enonce1,useragent" HISTORYDATECONTROL @@ -6810,7 +6790,6 @@ static void clean_up(ckpool_t *ckp) fclose(ckp->logfp); } -// TODO: skip ones not needed for confirm_summaries() static void alloc_storage() { workqueue_free = k_new_list("WorkQueue", sizeof(WORKQUEUE), @@ -8509,6 +8488,7 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in The value of diff_want defaults to the block's network difficulty (block_ndiff) but can be changed with diff_times and diff_add to: block_ndiff * diff_times + diff_add + N.B. diff_times and diff_add can be zero, positive or negative The pplns_elapsed time of the shares is from the createdate of the begin_workinfoid that has shares accounted to the total, up to the createdate of the last share @@ -10411,11 +10391,8 @@ static void confirm_reload() /* The last workinfo we should process * The reason for going past the last 'a' up to before * the first 'n' is in case there were shares missed between them - - * but that should only be the case with a code bug - so it checks that - * TODO: auto aging will clear 'n' sections inside the 'a's that - * will always occur when ckpool restarts, since ckpool will never - * send workinfo age records for workinfo that's active at shutdown - - * Aging these can (for now) easily be done manually in psql */ + * but that should only be the case with a code bug - + * so it checks that */ if (dbstatus.newest_workinfoid_a > 0) { confirm_last_workinfoid = dbstatus.newest_workinfoid_a; last_reason = "newest aged"; From e5c320c577d1e5b7f1a44cf5764424e129f05948 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 14:18:10 +1000 Subject: [PATCH 02/14] ckdb - pplns error if diff_want < 1 --- src/ckdb.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index ea3c723e..ca013c04 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -8580,6 +8580,13 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, hex2bin(ndiffbin, DATA_WORKINFO(w_item)->bits, 4); ndiff = diff_from_nbits(ndiffbin); diff_want = ndiff * diff_times + diff_add; + if (diff_want < 1.0) { + snprintf(reply, siz, + "ERR.invalid diff_want result %f", + diff_want); + return strdup(reply); + } + begin_workinfoid = 0; share_count = 0; total = 0; @@ -8614,7 +8621,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, break; default: snprintf(reply, siz, - "ERR.sharesummary not ready in workinfo %"PRId64, + "ERR.sharesummary1 not ready in workinfo %"PRId64, DATA_SHARESUMMARY(ss_item)->workinfoid); goto shazbot; } @@ -8639,7 +8646,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, break; default: snprintf(reply, siz, - "ERR.sharesummary not ready in workinfo %"PRId64, + "ERR.sharesummary2 not ready in workinfo %"PRId64, DATA_SHARESUMMARY(ss_item)->workinfoid); goto shazbot; } From 2feed25c5c30ad10ea793c5a4ec6518b950e071f Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 16:21:31 +1000 Subject: [PATCH 03/14] ckdb/sql - update db to v0.8 and add preauth --- sql/ckdb.sql | 10 ++++++++-- sql/v0.7-v0.8.sql | 32 ++++++++++++++++++++++++++++++++ src/ckdb.c | 26 ++++++++++++++++++-------- 3 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 sql/v0.7-v0.8.sql diff --git a/sql/ckdb.sql b/sql/ckdb.sql index 374d753c..62e85614 100644 --- a/sql/ckdb.sql +++ b/sql/ckdb.sql @@ -289,7 +289,12 @@ CREATE TABLE blocks ( nonce2 character varying(256) NOT NULL, nonce character varying(64) NOT NULL, reward bigint NOT NULL, -- satoshis - confirmed char DEFAULT '' NOT NULL, -- blank, 'c'onfirmed or 'o'rphan + confirmed char DEFAULT '' NOT NULL, + diffacc float DEFAULT 0 NOT NULL, + differr float DEFAULT 0 NOT NULL, + sharecount bigint DEFAULT 0 NOT NULL, + errorcount bigint DEFAULT 0 NOT NULL, + elapsed bigint DEFAULT 0 NOT NULL, createdate timestamp with time zone NOT NULL, createby character varying(64) DEFAULT ''::character varying NOT NULL, createcode character varying(128) DEFAULT ''::character varying NOT NULL, @@ -340,6 +345,7 @@ CREATE TABLE auths ( clientid integer NOT NULL, enonce1 character varying(64) NOT NULL, useragent character varying(256) NOT NULL, + preauth char DEFAULT 'N' NOT NULL, createdate timestamp with time zone NOT NULL, createby character varying(64) DEFAULT ''::character varying NOT NULL, createcode character varying(128) DEFAULT ''::character varying NOT NULL, @@ -391,4 +397,4 @@ CREATE TABLE version ( PRIMARY KEY (vlock) ); -insert into version (vlock,version) values (1,'0.7'); +insert into version (vlock,version) values (1,'0.8'); diff --git a/sql/v0.7-v0.8.sql b/sql/v0.7-v0.8.sql new file mode 100644 index 00000000..c0c5360e --- /dev/null +++ b/sql/v0.7-v0.8.sql @@ -0,0 +1,32 @@ +SET SESSION AUTHORIZATION 'postgres'; + +BEGIN transaction; + +DO $$ +DECLARE ver TEXT; +BEGIN + + UPDATE version set version='0.8' where vlock=1 and version='0.7'; + + IF found THEN + RETURN; + END IF; + + SELECT version into ver from version + WHERE vlock=1; + + RAISE EXCEPTION 'Wrong DB version - expect "0.7" - found "%"', ver; + +END $$; + +ALTER TABLE ONLY auths + ADD COLUMN preauth char DEFAULT 'N' NOT NULL; + +ALTER TABLE ONLY blocks + ADD COLUMN diffacc float DEFAULT 0 NOT NULL, + ADD COLUMN differr float DEFAULT 0 NOT NULL, + ADD COLUMN sharecount bigint DEFAULT 0 NOT NULL, + ADD COLUMN errorcount bigint DEFAULT 0 NOT NULL, + ADD COLUMN elapsed bigint DEFAULT 0 NOT NULL; + +END transaction; diff --git a/src/ckdb.c b/src/ckdb.c index ca013c04..72f55bc1 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -46,8 +46,8 @@ */ #define DB_VLOCK "1" -#define DB_VERSION "0.7" -#define CKDB_VERSION DB_VERSION"-0.106" +#define DB_VERSION "0.8" +#define CKDB_VERSION DB_VERSION"-0.200" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -841,6 +841,8 @@ static K_LIST *transfer_free; // older version missing field defaults static TRANSFER auth_1 = { "poolinstance", "", auth_1.value }; static K_ITEM auth_poolinstance = { "tmp", NULL, NULL, (void *)(&auth_1) }; +static TRANSFER auth_2 = { "preauth", FALSE_STR, auth_2.value }; +static K_ITEM auth_preauth = { "tmp", NULL, NULL, (void *)(&auth_2) }; static TRANSFER poolstats_1 = { "elapsed", "0", poolstats_1.value }; static K_ITEM poolstats_elapsed = { "tmp", NULL, NULL, (void *)(&poolstats_1) }; static TRANSFER userstats_1 = { "elapsed", "0", userstats_1.value }; @@ -1254,6 +1256,7 @@ typedef struct auths { int32_t clientid; char enonce1[TXT_SML+1]; char useragent[TXT_BIG+1]; + char preauth[TXT_FLAG+1]; HISTORYDATECONTROLFIELDS; } AUTHS; @@ -5554,8 +5557,8 @@ static cmp_t cmp_auths(K_ITEM *a, K_ITEM *b) static char *auths_add(PGconn *conn, char *poolinstance, char *username, char *workername, char *clientid, char *enonce1, - char *useragent, char *by, char *code, char *inet, - tv_t *cd, bool igndup, K_TREE *trf_root) + char *useragent, char *preauth, char *by, char *code, + char *inet, tv_t *cd, bool igndup, K_TREE *trf_root) { ExecStatusType rescode; bool conned = false; @@ -5567,7 +5570,7 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, AUTHS *row; char *ins; char *secuserid = NULL; - char *params[7 + HISTORYDATECOUNT]; + char *params[8 + HISTORYDATECOUNT]; int par; LOGDEBUG("%s(): add", __func__); @@ -5594,6 +5597,7 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, TXT_TO_INT("clientid", clientid, row->clientid); STRNCPY(row->enonce1, enonce1); STRNCPY(row->useragent, useragent); + STRNCPY(row->preauth, preauth); HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATETRANSFER(trf_root, row); @@ -5633,12 +5637,13 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, params[par++] = int_to_buf(row->clientid, NULL, 0); params[par++] = str_to_buf(row->enonce1, NULL, 0); params[par++] = str_to_buf(row->useragent, NULL, 0); + params[par++] = str_to_buf(row->preauth, NULL, 0); HISTORYDATEPARAMS(params, par, row); PARCHK(par, params); ins = "insert into auths " - "(authid,poolinstance,userid,workername,clientid,enonce1,useragent" - HISTORYDATECONTROL ") values (" PQPARAM12 ")"; + "(authid,poolinstance,userid,workername,clientid,enonce1,useragent,preauth" + HISTORYDATECONTROL ") values (" PQPARAM13 ")"; res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE); rescode = PQresultStatus(res); @@ -8223,7 +8228,7 @@ static char *cmd_auth_do(PGconn *conn, char *cmd, char *id, char *by, char reply[1024] = ""; size_t siz = sizeof(reply); K_ITEM *i_poolinstance, *i_username, *i_workername, *i_clientid; - K_ITEM *i_enonce1, *i_useragent; + K_ITEM *i_enonce1, *i_useragent, *i_preauth; char *secuserid; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -8252,12 +8257,17 @@ static char *cmd_auth_do(PGconn *conn, char *cmd, char *id, char *by, if (!i_useragent) return strdup(reply); + i_preauth = optional_name(trf_root, "preauth", 1, NULL); + if (!i_preauth) + i_preauth = &auth_preauth; + secuserid = auths_add(conn, DATA_TRANSFER(i_poolinstance)->data, DATA_TRANSFER(i_username)->data, DATA_TRANSFER(i_workername)->data, DATA_TRANSFER(i_clientid)->data, DATA_TRANSFER(i_enonce1)->data, DATA_TRANSFER(i_useragent)->data, + DATA_TRANSFER(i_preauth)->data, by, code, inet, cd, igndup, trf_root); if (!secuserid) { From bf602d4a18607b9c73da59227f51ae46ea2c2195 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 16:46:22 +1000 Subject: [PATCH 04/14] ckdb/php - add/show block find time to blocklist --- pool/page_blocks.php | 2 +- src/ckdb.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pool/page_blocks.php b/pool/page_blocks.php index 8d682fee..0168b8d2 100644 --- a/pool/page_blocks.php +++ b/pool/page_blocks.php @@ -36,7 +36,7 @@ function doblocks($data, $user) $pg .= "".$ans['height'.$i].''; $pg .= "".$ans['workername'.$i].''; $pg .= "".btcfmt($ans['reward'.$i]).''; - $pg .= "".gmdate('Y-m-d H:i:s+00', $ans['createdate'.$i]).''; + $pg .= "".gmdate('Y-m-d H:i:s+00', $ans['firstcreatedate'.$i]).''; $pg .= "".$stat.''; $pg .= "\n"; } diff --git a/src/ckdb.c b/src/ckdb.c index 72f55bc1..7024c0a0 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -47,7 +47,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.8" -#define CKDB_VERSION DB_VERSION"-0.200" +#define CKDB_VERSION DB_VERSION"-0.201" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -7256,6 +7256,8 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, char tmp[1024]; char *buf; size_t len, off; + int32_t height = -1; + tv_t first_cd = {0,0}; int rows; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -7266,6 +7268,10 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, K_RLOCK(blocks_free); b_item = last_in_ktree(blocks_root, ctx); while (b_item && rows < 42) { + if (height != DATA_BLOCKS(b_item)->height) { + height = DATA_BLOCKS(b_item)->height; + copy_tv(&first_cd, &(DATA_BLOCKS(b_item)->createdate)); + } if (CURRENT(&(DATA_BLOCKS(b_item)->expirydate))) { int_to_buf(DATA_BLOCKS(b_item)->height, reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "height%d=%s%c", rows, reply, FLDSEP); @@ -7287,6 +7293,11 @@ static char *cmd_blocklist(__maybe_unused PGconn *conn, char *cmd, char *id, snprintf(tmp, sizeof(tmp), "workername%d=%s%c", rows, reply, FLDSEP); APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), + "firstcreatedate%d=%ld%c", rows, + first_cd.tv_sec, FLDSEP); + APPEND_REALLOC(buf, off, len, tmp); + snprintf(tmp, sizeof(tmp), "createdate%d=%ld%c", rows, DATA_BLOCKS(b_item)->createdate.tv_sec, FLDSEP); From f3f067ebc11dd490930016c1bba90ef29d864914 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 17:56:32 +1000 Subject: [PATCH 05/14] ckdb - add address authorisation --- src/ckdb.c | 182 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 49 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 7024c0a0..58d21d88 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -767,6 +767,7 @@ enum cmd_values { CMD_LOGLEVEL, CMD_SHARELOG, CMD_AUTH, + CMD_ADDRAUTH, CMD_ADDUSER, CMD_NEWPASS, CMD_CHKPASS, @@ -2478,7 +2479,7 @@ unparam: return ok; } -static bool users_add(PGconn *conn, char *username, char *emailaddress, +static 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) { @@ -2571,7 +2572,10 @@ unitem: } K_WUNLOCK(users_free); - return ok; + if (ok) + return item; + else + return NULL; } static bool users_fill(PGconn *conn) @@ -5558,7 +5562,8 @@ static cmp_t cmp_auths(K_ITEM *a, K_ITEM *b) static char *auths_add(PGconn *conn, char *poolinstance, char *username, char *workername, char *clientid, char *enonce1, char *useragent, char *preauth, char *by, char *code, - char *inet, tv_t *cd, bool igndup, K_TREE *trf_root) + char *inet, tv_t *cd, bool igndup, K_TREE *trf_root, + bool addressuser) { ExecStatusType rescode; bool conned = false; @@ -5584,8 +5589,18 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, K_RLOCK(users_free); u_item = find_users(username); K_RUNLOCK(users_free); - if (!u_item) - goto unitem; + if (!u_item) { + if (addressuser) { + if (conn == NULL) { + conn = dbconnect(); + conned = true; + } + u_item = users_add(conn, username, EMPTY, EMPTY, + by, code, inet, cd, trf_root); + } + if (!u_item) + goto unitem; + } STRNCPY(row->poolinstance, poolinstance); row->userid = DATA_USERS(u_item)->userid; @@ -5607,6 +5622,9 @@ static char *auths_add(PGconn *conn, char *poolinstance, char *username, k_add_head(auths_free, a_item); K_WUNLOCK(auths_free); + if (conned) + PQfinish(conn); + if (!igndup) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); LOGERR("%s(): Duplicate auths ignored %s/%s/%s", @@ -6939,9 +6957,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; - bool ok; + K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -6957,12 +6973,12 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by, if (!i_passwordhash) return strdup(reply); - ok = users_add(conn, DATA_TRANSFER(i_username)->data, - DATA_TRANSFER(i_emailaddress)->data, - DATA_TRANSFER(i_passwordhash)->data, - by, code, inet, now, trf_root); + u_item = users_add(conn, DATA_TRANSFER(i_username)->data, + DATA_TRANSFER(i_emailaddress)->data, + DATA_TRANSFER(i_passwordhash)->data, + by, code, inet, now, trf_root); - if (!ok) { + if (!u_item) { LOGERR("%s() %s.failed.DBE", __func__, id); return strdup("failed.DBE"); } @@ -8279,7 +8295,7 @@ static char *cmd_auth_do(PGconn *conn, char *cmd, char *id, char *by, DATA_TRANSFER(i_enonce1)->data, DATA_TRANSFER(i_useragent)->data, DATA_TRANSFER(i_preauth)->data, - by, code, inet, cd, igndup, trf_root); + by, code, inet, cd, igndup, trf_root, false); if (!secuserid) { LOGDEBUG("%s() %s.failed.DBE", __func__, id); @@ -8309,6 +8325,83 @@ static char *cmd_auth(PGconn *conn, char *cmd, char *id, return cmd_auth_do(conn, cmd, id, by, code, inet, cd, igndup, trf_root); } +static char *cmd_addrauth_do(PGconn *conn, char *cmd, char *id, char *by, + char *code, char *inet, tv_t *cd, bool igndup, + K_TREE *trf_root) +{ + char reply[1024] = ""; + size_t siz = sizeof(reply); + K_ITEM *i_poolinstance, *i_username, *i_workername, *i_clientid; + K_ITEM *i_enonce1, *i_useragent, *i_preauth; + char *secuserid; + + LOGDEBUG("%s(): cmd '%s'", __func__, cmd); + + i_poolinstance = optional_name(trf_root, "poolinstance", 1, NULL); + if (!i_poolinstance) + i_poolinstance = &auth_poolinstance; + + i_username = require_name(trf_root, "username", 1, NULL, reply, siz); + if (!i_username) + return strdup(reply); + + i_workername = require_name(trf_root, "workername", 1, NULL, reply, siz); + if (!i_workername) + return strdup(reply); + + i_clientid = require_name(trf_root, "clientid", 1, NULL, reply, siz); + if (!i_clientid) + return strdup(reply); + + i_enonce1 = require_name(trf_root, "enonce1", 1, NULL, reply, siz); + if (!i_enonce1) + return strdup(reply); + + i_useragent = require_name(trf_root, "useragent", 0, NULL, reply, siz); + if (!i_useragent) + return strdup(reply); + + i_preauth = require_name(trf_root, "preauth", 1, NULL, reply, siz); + if (!i_preauth) + return strdup(reply); + + secuserid = auths_add(conn, DATA_TRANSFER(i_poolinstance)->data, + DATA_TRANSFER(i_username)->data, + DATA_TRANSFER(i_workername)->data, + DATA_TRANSFER(i_clientid)->data, + DATA_TRANSFER(i_enonce1)->data, + DATA_TRANSFER(i_useragent)->data, + DATA_TRANSFER(i_preauth)->data, + by, code, inet, cd, igndup, trf_root, true); + + if (!secuserid) { + LOGDEBUG("%s() %s.failed.DBE", __func__, id); + return strdup("failed.DBE"); + } + + LOGDEBUG("%s.ok.auth added for %s", id, secuserid); + snprintf(reply, siz, "ok.%s", secuserid); + return strdup(reply); +} + +static char *cmd_addrauth(PGconn *conn, char *cmd, char *id, + __maybe_unused tv_t *now, char *by, + char *code, char *inet, tv_t *cd, + K_TREE *trf_root) +{ + bool igndup = false; + + // confirm_summaries() doesn't call this + if (reloading) { + if (tv_equal(cd, &(dbstatus.newest_createdate_auths))) + igndup = true; + else if (tv_newer(cd, &(dbstatus.newest_createdate_auths))) + return NULL; + } + + return cmd_addrauth_do(conn, cmd, id, by, code, inet, cd, igndup, trf_root); +} + static char *cmd_homepage(__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, @@ -8972,6 +9065,7 @@ static struct CMDS { { CMD_SHARELOG, STR_SHAREERRORS, 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_ADDRAUTH, "addrauth", false, true, cmd_addrauth, ACCESS_POOL }, { 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 }, @@ -9478,6 +9572,16 @@ static void *logger(__maybe_unused void *arg) return NULL; } +#define STORELASTREPLY(_cmd) do { \ + if (last_ ## _cmd) \ + free(last_ ## _cmd); \ + last_ ## _cmd = buf; \ + buf = NULL; \ + if (reply_ ## _cmd) \ + free(reply_ ## _cmd); \ + reply_ ## _cmd = rep; \ + } while (0) + static void *socketer(__maybe_unused void *arg) { proc_instance_t *pi = (proc_instance_t *)arg; @@ -9485,6 +9589,7 @@ static void *socketer(__maybe_unused void *arg) char *end, *ans = NULL, *rep = NULL, *buf = NULL, *dot; char cmd[CMD_SIZ+1], id[ID_SIZ+1], reply[1024+1]; char *last_auth = NULL, *reply_auth = NULL; + char *last_addrauth = NULL, *reply_addrauth = NULL; char *last_chkpass = NULL, *reply_chkpass = NULL; char *last_adduser = NULL, *reply_adduser = NULL; char *last_newpass = NULL, *reply_newpass = NULL; @@ -9555,6 +9660,7 @@ static void *socketer(__maybe_unused void *arg) * the reply without reprocessing the message */ dup = false; + // These are ordered approximately most likely first if (last_auth && strcmp(last_auth, buf) == 0) { reply_last = reply_auth; dup = true; @@ -9570,6 +9676,9 @@ static void *socketer(__maybe_unused void *arg) } else if (last_newid && strcmp(last_newid, buf) == 0) { reply_last = reply_newid; dup = true; + } else if (last_addrauth && strcmp(last_addrauth, buf) == 0) { + reply_last = reply_auth; + dup = true; } else if (last_web && strcmp(last_web, buf) == 0) { reply_last = reply_web; dup = true; @@ -9644,6 +9753,7 @@ static void *socketer(__maybe_unused void *arg) break; // Always process immediately: case CMD_AUTH: + case CMD_ADDRAUTH: // First message from the pool if (want_first) { ck_wlock(&fpm_lock); @@ -9670,49 +9780,22 @@ static void *socketer(__maybe_unused void *arg) ans = NULL; switch (cmdnum) { case CMD_AUTH: - if (last_auth) - free(last_auth); - last_auth = buf; - buf = NULL; - if (reply_auth) - free(reply_auth); - reply_auth = rep; + STORELASTREPLY(auth); + break; + case CMD_ADDRAUTH: + STORELASTREPLY(addrauth); break; case CMD_CHKPASS: - if (last_chkpass) - free(last_chkpass); - last_chkpass = buf; - buf = NULL; - if (reply_chkpass) - free(reply_chkpass); - reply_chkpass = rep; + STORELASTREPLY(chkpass); break; case CMD_ADDUSER: - if (last_adduser) - free(last_adduser); - last_adduser = buf; - buf = NULL; - if (reply_adduser) - free(reply_adduser); - reply_adduser = rep; + STORELASTREPLY(adduser); break; case CMD_NEWPASS: - if (last_newpass) - free(last_newpass); - last_newpass = buf; - buf = NULL; - if (reply_newpass) - free(reply_newpass); - reply_newpass = rep; + STORELASTREPLY(newpass); break; case CMD_NEWID: - if (last_newid) - free(last_newid); - last_newid = buf; - buf = NULL; - if (reply_newid) - free(reply_newid); - reply_newid = rep; + STORELASTREPLY(newid); break; default: free(rep); @@ -9912,6 +9995,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf) __func__, count, cmd); break; case CMD_AUTH: + case CMD_ADDRAUTH: case CMD_POOLSTAT: case CMD_USERSTAT: case CMD_BLOCK: From 7adda73161e241c07fb73c6f3928f271226d5b28 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 17:58:32 +1000 Subject: [PATCH 06/14] ckdb - remove code comments re addrauth --- src/ckdb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 58d21d88..39738ee5 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -128,8 +128,6 @@ static char *restorefrom; * ckdb aborting and needing a complete restart resolves it * The users table, required for the authorise messages, is always updated * immediately and is not affected by ckpool messages until we - * TODO: allow bitcoin addresses - this will also need to be handled - * while filling the queue during reload, once we allow BTC addresses * During the reload, when checking the timeframe for summarisation, we * use the current last userstats createdate as 'now' to avoid touching a * timeframe where data could still be waiting to be loaded @@ -3993,7 +3991,6 @@ static bool shares_add(PGconn *conn, char *workinfoid, char *username, char *wor shares = DATA_SHARES(s_item); - // TODO: allow BTC address later? K_RLOCK(users_free); u_item = find_users(username); K_RUNLOCK(users_free); @@ -4133,7 +4130,6 @@ static bool shareerrors_add(PGconn *conn, char *workinfoid, char *username, shareerrors = DATA_SHAREERRORS(s_item); - // TODO: allow BTC address later? K_RLOCK(users_free); u_item = find_users(username); K_RUNLOCK(users_free); From 68672b8852aad32d53ccfc0bceaaebce704004c2 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 18:03:32 +1000 Subject: [PATCH 07/14] ckdb - correct block message on confirm --- src/ckdb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 39738ee5..3e2eb20e 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -5157,9 +5157,10 @@ flail: } tv_to_buf(&(DATA_BLOCKS(b_item)->createdate), cd_buf, sizeof(cd_buf)); snprintf(tmp, sizeof(tmp), - " Reward: %f, User: %s, Worker: %s, ShareEst: %.1f %s%s%% UTC:%s", + " Reward: %f, Worker: %s, ShareEst: %.1f %s%s%% UTC:%s", BTC_TO_D(DATA_BLOCKS(b_item)->reward), - username, workername, pool.diffacc, est, pct, cd_buf); + DATA_BLOCKS(b_item)->workername, + pool.diffacc, est, pct, cd_buf); if (pool.workinfoid < DATA_BLOCKS(b_item)->workinfoid) { pool.workinfoid = DATA_BLOCKS(b_item)->workinfoid; pool.diffacc = pool.differr = From 51ce45c40fa4f6316dba896666f8035b576c7cc8 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sun, 31 Aug 2014 18:32:50 +1000 Subject: [PATCH 08/14] ckdb - correct block messages --- src/ckdb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 3e2eb20e..6393e6b3 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -5009,13 +5009,12 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, k_add_head(blocks_free, b_item); K_WUNLOCK(blocks_free); // No mismatch messages during startup - if (!startup_complete) { + if (startup_complete) { tv_to_buf(cd, cd_buf, sizeof(cd_buf)); - LOGERR("%s(): Request Status: %s requires Status: %s. " + LOGERR("%s(): New Status: %s requires Status: %c. " "Ignored: Status: %s, Block: %s/...%s/%s", __func__, - blocks_confirmed(confirmed), - blocks_confirmed(BLOCKS_CONFIRM_STR), + blocks_confirmed(confirmed), want, blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), height, blk_dsp, cd_buf); } @@ -8218,7 +8217,10 @@ static char *cmd_blocks_do(PGconn *conn, char *cmd, char *id, char *by, } if (!ok) { - LOGERR("%s() %s.failed.DBE", __func__, id); + /* Ignore during startup, + * another error should have shown if it matters */ + if (startup_complete) + LOGERR("%s() %s.failed.DBE", __func__, id); return strdup("failed.DBE"); } From 4d34d9d1b3f3002d094f8e4a22d183cfb2154ce0 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 08:33:28 +1000 Subject: [PATCH 09/14] ckdb - add full block table locking (in advance) --- src/ckdb.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ckdb.c b/src/ckdb.c index 6393e6b3..fe6d20cb 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -8439,7 +8439,9 @@ static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id, } // TODO: handle orphans + K_RLOCK(blocks_free); b_item = last_in_ktree(blocks_root, ctx); + K_RUNLOCK(blocks_free); if (b_item) { tvs_to_buf(&(DATA_BLOCKS(b_item)->createdate), reply, sizeof(reply)); snprintf(tmp, sizeof(tmp), "lastblock=%s%cconfirmed=%s%c", @@ -8666,8 +8668,10 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, blocks.height = height + 1; blocks.blockhash[0] = '\0'; look.data = (void *)(&blocks); + K_RLOCK(blocks_free); b_item = find_before_in_ktree(blocks_root, &look, cmp_blocks, ctx); if (!b_item) { + K_RUNLOCK(blocks_free); snprintf(reply, siz, "ERR.no block height %d", height); return strdup(reply); } @@ -8676,6 +8680,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id, break; b_item = prev_in_ktree(ctx); } + K_RUNLOCK(blocks_free); if (!b_item || DATA_BLOCKS(b_item)->height != height) { snprintf(reply, siz, "ERR.unconfirmed block %d", height); return strdup(reply); From 22a337e4cd101b862b03b693ce1a902ef98435bf Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 09:01:42 +1000 Subject: [PATCH 10/14] ckdb - version --- src/ckdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ckdb.c b/src/ckdb.c index fe6d20cb..65bbed8a 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -47,7 +47,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.8" -#define CKDB_VERSION DB_VERSION"-0.201" +#define CKDB_VERSION DB_VERSION"-0.202" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ From 7f2f81736aaaf848f0d8aa1b859f1ad6b238c080 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 11:03:06 +1000 Subject: [PATCH 11/14] ckdb - dsp_blocks for debugging and a function dsp_hash for formatting a hash --- src/ckdb.c | 53 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 65bbed8a..5324c3cb 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -4819,6 +4819,38 @@ void sharesummary_reload() PQfinish(conn); } +// TODO: do this better ... :) +static void dsp_hash(char *hash, char *buf, size_t siz) +{ + char *ptr; + + ptr = hash + strlen(hash) - (siz - 1) - 8; + if (ptr < hash) + ptr = hash; + STRNCPYSIZ(buf, ptr, siz); +} + +static void dsp_blocks(K_ITEM *item, FILE *stream) +{ + char createdate_buf[DATE_BUFSIZ], expirydate_buf[DATE_BUFSIZ]; + BLOCKS *b = NULL; + char hash_dsp[16+1]; + + if (!item) + fprintf(stream, "%s() called with (null) item\n", __func__); + else { + b = DATA_BLOCKS(item); + + dsp_hash(b->blockhash, hash_dsp, sizeof(hash_dsp)); + tv_to_buf(&(b->createdate), createdate_buf, sizeof(createdate_buf)); + tv_to_buf(&(b->expirydate), expirydate_buf, sizeof(expirydate_buf)); + fprintf(stream, " hi=%d hash='%.16s' uid=%"PRId64" w='%s' " + "cd=%s ed=%s\n", + b->height, hash_dsp, b->userid, b->workername, + createdate_buf, expirydate_buf); + } +} + // order by height asc,blockhash asc,expirydate desc static cmp_t cmp_blocks(K_ITEM *a, K_ITEM *b) { @@ -4879,7 +4911,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, K_TREE_CTX ctx[1]; K_ITEM *b_item, *u_item, *old_b_item; char cd_buf[DATE_BUFSIZ]; - char blk_dsp[16+1], *ptr; + char hash_dsp[16+1]; BLOCKS *row; char *upd, *ins; char *params[11 + HISTORYDATECOUNT]; @@ -4901,11 +4933,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, 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); + dsp_hash(blockhash, hash_dsp, sizeof(hash_dsp)); K_WLOCK(blocks_free); old_b_item = find_blocks(row->height, blockhash); @@ -4923,7 +4951,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, __func__, blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), blocks_confirmed(confirmed), - height, blk_dsp, cd_buf); + height, hash_dsp, cd_buf); } return true; } @@ -4990,7 +5018,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, "Ignored: Block: %s/...%s/%s", __func__, blocks_confirmed(confirmed), - height, blk_dsp, cd_buf); + height, hash_dsp, cd_buf); goto flail; } want = BLOCKS_CONFIRM; @@ -5000,7 +5028,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, tv_to_buf(cd, cd_buf, sizeof(cd_buf)); LOGERR("%s(): Can't %s a non-existent Block: %s/...%s/%s", __func__, blocks_confirmed(confirmed), - height, blk_dsp, cd_buf); + height, hash_dsp, cd_buf); goto flail; } if (confirmed[0] == BLOCKS_CONFIRM) @@ -5016,7 +5044,7 @@ static bool blocks_add(PGconn *conn, char *height, char *blockhash, __func__, blocks_confirmed(confirmed), want, blocks_confirmed(DATA_BLOCKS(old_b_item)->confirmed), - height, blk_dsp, cd_buf); + height, hash_dsp, cd_buf); } goto flail; } @@ -5177,7 +5205,7 @@ flail: LOGWARNING("%s(): %sStatus: %s, Block: %s/...%s%s", __func__, blk ? "BLOCK! " : "", blocks_confirmed(confirmed), - height, blk_dsp, tmp); + height, hash_dsp, tmp); } return ok; @@ -6867,6 +6895,7 @@ static void alloc_storage() ALLOC_BLOCKS, LIMIT_BLOCKS, true); blocks_store = k_new_store(blocks_free); blocks_root = new_ktree(); + blocks_free->dsp_func = dsp_blocks; miningpayouts_free = k_new_list("MiningPayouts", sizeof(MININGPAYOUTS), ALLOC_MININGPAYOUTS, LIMIT_MININGPAYOUTS, true); @@ -8923,6 +8952,8 @@ static char *cmd_dsp(__maybe_unused PGconn *conn, __maybe_unused char *cmd, if (!i_file) return strdup(reply); + dsp_ktree(blocks_free, blocks_root, DATA_BLOCKS(i_file)->data, NULL); + dsp_ktree(transfer_free, trf_root, DATA_TRANSFER(i_file)->data, NULL); dsp_ktree(sharesummary_free, sharesummary_root, DATA_TRANSFER(i_file)->data, NULL); From 6beefc3e44e6d6ee28e4486717b756d2215e269d Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 13:18:16 +1000 Subject: [PATCH 12/14] php - comment in socket --- pool/socket.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pool/socket.php b/pool/socket.php index 9ace00b7..f2108653 100644 --- a/pool/socket.php +++ b/pool/socket.php @@ -144,7 +144,10 @@ function sendsock($fun, $msg) } return $ret; } -# +# This is the only function in here you call +# You pass it a string $fun for debugging +# and the data $msg to send to ckdb +# and it returns $ret = false on error or $ret = the string reply function sendsockreply($fun, $msg) { $ret = false; From 3e2d297d14062b1edec4ebbb8abfbf2070da8a6a Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 13:25:47 +1000 Subject: [PATCH 13/14] php - db.php comment --- pool/db.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pool/db.php b/pool/db.php index d47931e8..88947a12 100644 --- a/pool/db.php +++ b/pool/db.php @@ -3,6 +3,17 @@ include_once('socket.php'); include_once('base.php'); # +# List of db fucntions to call and get the results +# back from ckdb +# From homeInfo and the rest after that +# The result is an array of all ckdb result field names and their values +# Also is included: +# ['ID'] the id sent +# ['STAMP'] the ckdb reply timestamp +# ['STATUS'] the ckdb reply status (!'ok' = error) +# ['ERROR'] if status not 'ok' the error message reply +# The reply is false if the ckdb return data was corrupt +# global $send_sep, $fld_sep, $val_sep; $send_sep = '.'; $fld_sep = Chr(0x9); From 0377adc8a1b600043fc85551cc8a70c41c628869 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 1 Sep 2014 13:31:00 +1000 Subject: [PATCH 14/14] php - spelling etc --- pool/db.php | 7 +++---- pool/socket.php | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pool/db.php b/pool/db.php index 88947a12..09f3897f 100644 --- a/pool/db.php +++ b/pool/db.php @@ -3,11 +3,10 @@ include_once('socket.php'); include_once('base.php'); # -# List of db fucntions to call and get the results -# back from ckdb -# From homeInfo and the rest after that +# List of db functions to call and get the results back from ckdb +# From homeInfo() and the rest after that # The result is an array of all ckdb result field names and their values -# Also is included: +# Also included: # ['ID'] the id sent # ['STAMP'] the ckdb reply timestamp # ['STATUS'] the ckdb reply status (!'ok' = error) diff --git a/pool/socket.php b/pool/socket.php index f2108653..ad10a1f2 100644 --- a/pool/socket.php +++ b/pool/socket.php @@ -1,5 +1,7 @@