Merge branch 'master' of bitbucket.org:ckolivas/ckpool
This commit is contained in:
commit
79367129f3
@ -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: 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;}
|
||||
#n42 div.sub {left: 0px; z-index: 42; position: absolute; visibility: hidden;}
|
||||
|
||||
@ -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 = '<br><table cellpadding=0 cellspacing=0 border=0>';
|
||||
@ -159,6 +159,7 @@ Block: <input type=text name=blk size=10 value='$blkuse'>
|
||||
$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: <input type=text name=blk size=10 value='$blkuse'>
|
||||
|
||||
$pg = '<br><a href=https://blockchain.info/block-height/';
|
||||
$pg .= $ans['block'].'>Blockchain '.$ans['block']."</a><br>\n";
|
||||
|
||||
if (strlen($ans['block_extra']) > 0)
|
||||
{
|
||||
$pg .= '<br><span class=err>';
|
||||
$msg = $ans['block_status'].' - '.$ans['block_extra'];
|
||||
$pg .= str_replace(' ', ' ', $msg)."</span><br>\n";
|
||||
}
|
||||
|
||||
if (strlen($ans['share_status']) > 0)
|
||||
{
|
||||
$pg .= '<br><span class=err>';
|
||||
$msg = $ans['share_status']." - Can't be paid out yet";
|
||||
$pg .= str_replace(' ', ' ', $msg)."</span><br>\n";
|
||||
}
|
||||
|
||||
$pg .= "<br><table callpadding=0 cellspacing=0 border=0>\n";
|
||||
$pg .= '<tr class=title>';
|
||||
$pg .= '<td class=dl>Name</td>';
|
||||
|
||||
@ -69,8 +69,9 @@ function check()
|
||||
'API' => 'api'
|
||||
),
|
||||
'Help' => array(
|
||||
'Help' => 'help',
|
||||
'Payouts' => 'payout'
|
||||
'Payouts' => 'payout',
|
||||
'Workers ' => 'workers',
|
||||
'Blocks' => 'blocks'
|
||||
)
|
||||
);
|
||||
tryLogInOut();
|
||||
|
||||
19
src/ckdb.c
19
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";
|
||||
@ -1652,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,
|
||||
@ -2048,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;
|
||||
@ -2151,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;
|
||||
@ -2251,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__,
|
||||
@ -2293,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);
|
||||
@ -2499,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;
|
||||
|
||||
23
src/ckdb.h
23
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.645"
|
||||
|
||||
#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;
|
||||
@ -295,6 +303,7 @@ enum cmd_values {
|
||||
CMD_DSP,
|
||||
CMD_STATS,
|
||||
CMD_PPLNS,
|
||||
CMD_USERSTATUS,
|
||||
CMD_END
|
||||
};
|
||||
|
||||
@ -603,7 +612,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)
|
||||
@ -632,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;
|
||||
@ -1334,6 +1344,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);
|
||||
|
||||
@ -1534,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);
|
||||
|
||||
255
src/ckdb_cmd.c
255
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);
|
||||
@ -85,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;
|
||||
}
|
||||
@ -223,7 +236,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);
|
||||
@ -248,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;
|
||||
@ -2909,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
|
||||
@ -2922,21 +2941,26 @@ 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: redesign to include workmarkers
|
||||
* ... before next payout that extends into a markersummary ... */
|
||||
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;
|
||||
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;
|
||||
@ -2945,12 +2969,12 @@ 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];
|
||||
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;
|
||||
@ -2996,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));
|
||||
@ -3031,31 +3067,26 @@ 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';
|
||||
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(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 */
|
||||
while (ss_item && total < diff_want) {
|
||||
while (total < diff_want && ss_item) {
|
||||
switch (sharesummary->complete[0]) {
|
||||
case SUMMARY_CONFIRM:
|
||||
break;
|
||||
@ -3063,14 +3094,9 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
|
||||
if (allow_aged)
|
||||
break;
|
||||
default:
|
||||
K_RUNLOCK(sharesummary_free);
|
||||
snprintf(reply, siz,
|
||||
"ERR.sharesummary1 not ready in "
|
||||
"workinfo %"PRId64,
|
||||
sharesummary->workinfoid);
|
||||
goto shazbot;
|
||||
share_status = "Not ready1";
|
||||
}
|
||||
share_count++;
|
||||
share_count += sharesummary->sharecount;
|
||||
total += (int64_t)(sharesummary->diffacc);
|
||||
begin_workinfoid = sharesummary->workinfoid;
|
||||
if (tv_newer(&end_tv, &(sharesummary->lastshare)))
|
||||
@ -3091,12 +3117,10 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
|
||||
if (allow_aged)
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
@ -3106,6 +3130,50 @@ 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_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 = EMPTY;
|
||||
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) {
|
||||
if (end_workinfoid == 0)
|
||||
end_workinfoid = workmarkers->workinfoidend;
|
||||
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) {
|
||||
@ -3140,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);
|
||||
@ -3379,6 +3454,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"
|
||||
@ -3479,7 +3617,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 }
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
@ -4055,6 +4061,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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user