Browse Source

ckdb/php - add PPS calculations for shifts

master
kanoi 9 years ago
parent
commit
885be5d715
  1. 5
      pool/base.php
  2. 28
      pool/page_shifts.php
  3. 15
      src/ckdb.h
  4. 13
      src/ckdb_cmd.c
  5. 73
      src/ckdb_data.c
  6. 17
      src/ckdb_dbio.c

5
pool/base.php

@ -126,8 +126,11 @@ function btcfmt($amt)
return number_format($amt, 8); return number_format($amt, 8);
} }
# #
function utcd($when) function utcd($when, $brief = false)
{ {
if ($brief)
return gmdate('M-d H:i:s', round($when));
else
return gmdate('Y-m-d H:i:s+00', round($when)); return gmdate('Y-m-d H:i:s+00', round($when));
} }
# #

28
pool/page_shifts.php

@ -4,10 +4,11 @@ function doshifts($data, $user)
{ {
$ans = getShifts($user); $ans = getShifts($user);
$pg = "<table callpadding=0 cellspacing=0 border=0>\n"; $pg = "Click <a href='#payoutmark'>here</a> to jump to the start of the last payout<br><br>";
$pg .= "<table callpadding=0 cellspacing=0 border=0>\n";
$pg .= "<tr class=title>"; $pg .= "<tr class=title>";
$pg .= "<td class=dl>Shift</td>"; $pg .= "<td class=dl>Shift</td>";
$pg .= "<td class=dl>Start</td>"; $pg .= "<td class=dl>Start UTC</td>";
$pg .= "<td class=dr>Length</td>"; $pg .= "<td class=dr>Length</td>";
$pg .= "<td class=dr>Your Diff</td>"; $pg .= "<td class=dr>Your Diff</td>";
$pg .= "<td class=dr>Inv Diff</td>"; $pg .= "<td class=dr>Inv Diff</td>";
@ -15,6 +16,8 @@ function doshifts($data, $user)
$pg .= "<td class=dr>Shares</td>"; $pg .= "<td class=dr>Shares</td>";
$pg .= "<td class=dr>Avg Share</td>"; $pg .= "<td class=dr>Avg Share</td>";
$pg .= "<td class=dr>Rewards</td>"; $pg .= "<td class=dr>Rewards</td>";
$pg .= "<td class=dr>PPS<span class=st1>*</span></td>";
$pg .= "<td class=dr>PPS%</td>";
$pg .= "</tr>\n"; $pg .= "</tr>\n";
if (($ans['STATUS'] != 'ok') || !isset($ans['prefix_all'])) if (($ans['STATUS'] != 'ok') || !isset($ans['prefix_all']))
@ -28,9 +31,13 @@ function doshifts($data, $user)
for ($i = 0; $i < $count; $i++) for ($i = 0; $i < $count; $i++)
{ {
$u = ''; $u = '';
$mark = '';
if (isset($ans['lastpayoutstart:'.$i]) if (isset($ans['lastpayoutstart:'.$i])
&& $ans['lastpayoutstart:'.$i] != '') && $ans['lastpayoutstart:'.$i] != '')
{
$u = 'u'; $u = 'u';
$mark = '<a name=payoutmark></a>';
}
if (($i % 2) == 0) if (($i % 2) == 0)
$row = "even$u"; $row = "even$u";
else else
@ -52,9 +59,9 @@ function doshifts($data, $user)
$btc = ' <img src=/BTCSym.png border=0>'; $btc = ' <img src=/BTCSym.png border=0>';
else else
$btc = ''; $btc = '';
$pg .= "<td class=dl>$shif$btc</td>"; $pg .= "<td class=dl>$shif$btc$mark</td>";
$start = $ans['start:'.$i]; $start = $ans['start:'.$i];
$pg .= '<td class=dl>'.utcd($start).'</td>'; $pg .= '<td class=dl>'.utcd($start, true).'</td>';
$nd = $ans['end:'.$i]; $nd = $ans['end:'.$i];
$elapsed = $nd - $start; $elapsed = $nd - $start;
$pg .= '<td class=dr>'.howmanyhrs($elapsed).'</td>'; $pg .= '<td class=dr>'.howmanyhrs($elapsed).'</td>';
@ -72,10 +79,23 @@ function doshifts($data, $user)
$avgsh = 0; $avgsh = 0;
$pg .= '<td class=dr>'.number_format($avgsh, 2).'</td>'; $pg .= '<td class=dr>'.number_format($avgsh, 2).'</td>';
$pg .= '<td class=dr>'.$ans['rewards:'.$i].'</td>'; $pg .= '<td class=dr>'.$ans['rewards:'.$i].'</td>';
$ppsr = (float)$ans['ppsrewarded:'.$i];
if ($ppsr > 0)
$ppsd = sprintf('%.3e', $ppsr);
else
$ppsd = '0';
$pg .= "<td class=dr>$ppsd</td>";
$ppsv = (float)$ans['ppsvalue:'.$i];
if ($ppsv > 0)
$pgot = number_format(100.0 * $ppsr / $ppsv, 2).'%';
else
$pgot = '?';
$pg .= "<td class=dr>$pgot</td>";
$pg .= "</tr>\n"; $pg .= "</tr>\n";
} }
} }
$pg .= "</table>\n"; $pg .= "</table>\n";
$pg .= "<span class=st1>*</span> The PPS value unit is satoshis<br>";
return $pg; return $pg;
} }

15
src/ckdb.h

@ -55,7 +55,7 @@
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "1.0.2" #define DB_VERSION "1.0.2"
#define CKDB_VERSION DB_VERSION"-1.300" #define CKDB_VERSION DB_VERSION"-1.301"
#define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ #define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -1294,6 +1294,7 @@ typedef struct optioncontrol {
// Value it must default to (to work properly) // Value it must default to (to work properly)
#define OPTIONCONTROL_HEIGHT 1 #define OPTIONCONTROL_HEIGHT 1
#define MAX_HEIGHT 999999999
// Test it here rather than obscuring the #define elsewhere // Test it here rather than obscuring the #define elsewhere
#if ((OPTIONCONTROL_HEIGHT+1) != START_POOL_HEIGHT) #if ((OPTIONCONTROL_HEIGHT+1) != START_POOL_HEIGHT)
@ -1346,6 +1347,13 @@ extern tv_t last_bc;
// current network diff // current network diff
extern double current_ndiff; extern double current_ndiff;
// Offset in binary coinbase1 of the block number
#define BLOCKNUM_OFFSET 42
// Initial block reward (satoshi)
#define REWARD_BASE 5000000000.0
// How many blocks per halving
#define REWARD_HALVE 210000.0
// SHARES shares.id.json={...} // SHARES shares.id.json={...}
typedef struct shares { typedef struct shares {
int64_t workinfoid; int64_t workinfoid;
@ -2090,6 +2098,8 @@ extern void sequence_report(bool lock);
#define REWARDOVERRIDE "MinerReward" #define REWARDOVERRIDE "MinerReward"
#define PPSOVERRIDE "PPSValue"
// Data free functions (first) // Data free functions (first)
#define FREE_ITEM(item) do { } while(0) #define FREE_ITEM(item) do { } while(0)
// TODO: make a macro for all other to use above macro // TODO: make a macro for all other to use above macro
@ -2264,7 +2274,7 @@ extern K_ITEM *find_first_paypayid(int64_t userid, int64_t payoutid, K_TREE_CTX
extern cmp_t cmp_accountbalance(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_accountbalance(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_accountbalance(int64_t userid); extern K_ITEM *find_accountbalance(int64_t userid);
extern cmp_t cmp_optioncontrol(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_optioncontrol(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height); extern K_ITEM *find_optioncontrol(char *optionname, const tv_t *now, int32_t height);
extern int64_t user_sys_setting(int64_t userid, char *setting_name, extern int64_t user_sys_setting(int64_t userid, char *setting_name,
int64_t setting_default, tv_t *now); int64_t setting_default, tv_t *now);
extern cmp_t cmp_workinfo(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_workinfo(K_ITEM *a, K_ITEM *b);
@ -2279,6 +2289,7 @@ extern bool workinfo_age(int64_t workinfoid, char *poolinstance, char *by,
char *code, char *inet, tv_t *cd, tv_t *ss_first, char *code, char *inet, tv_t *cd, tv_t *ss_first,
tv_t *ss_last, int64_t *ss_count, int64_t *s_count, tv_t *ss_last, int64_t *ss_count, int64_t *s_count,
int64_t *s_diff); int64_t *s_diff);
extern double workinfo_pps(K_ITEM *w_item, int64_t workinfoid, bool lock);
extern cmp_t cmp_shares(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_shares(K_ITEM *a, K_ITEM *b);
extern cmp_t cmp_shareerrors(K_ITEM *a, K_ITEM *b); extern cmp_t cmp_shareerrors(K_ITEM *a, K_ITEM *b);
extern void dsp_sharesummary(K_ITEM *item, FILE *stream); extern void dsp_sharesummary(K_ITEM *item, FILE *stream);

13
src/ckdb_cmd.c

@ -5383,6 +5383,16 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
rows, wm->rewards, FLDSEP); rows, wm->rewards, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
// Use %.15e -> 16 non-leading-zero decimal places
snprintf(tmp, sizeof(tmp), "ppsvalue:%d=%.15f%c",
rows, wm->pps_value, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
// Use %.15e -> 16 non-leading-zero decimal places
snprintf(tmp, sizeof(tmp), "ppsrewarded:%d=%.15e%c",
rows, wm->rewarded, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "lastpayoutstart:%d=%s%c", snprintf(tmp, sizeof(tmp), "lastpayoutstart:%d=%s%c",
rows, rows,
(wm->workinfoidstart == (wm->workinfoidstart ==
@ -5431,7 +5441,8 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c", snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c",
rows, FLDSEP, rows, FLDSEP,
"markerid,shift,start,end,rewards," "markerid,shift,start,end,rewards,"
"lastpayoutstart", FLDSEP); "ppsvalue,ppsrewarded,lastpayoutstart",
FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts"); snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts");

73
src/ckdb_data.c

@ -1822,7 +1822,7 @@ static bool _reward_override_name(int32_t height, char *buf, size_t siz,
} }
// Must be R or W locked before call // Must be R or W locked before call
K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height) K_ITEM *find_optioncontrol(char *optionname, const tv_t *now, int32_t height)
{ {
OPTIONCONTROL optioncontrol, *oc, *ocbest; OPTIONCONTROL optioncontrol, *oc, *ocbest;
K_TREE_CTX ctx[1]; K_TREE_CTX ctx[1];
@ -1832,6 +1832,9 @@ K_ITEM *find_optioncontrol(char *optionname, tv_t *now, int32_t height)
* 1) activationdate is <= now * 1) activationdate is <= now
* and * and
* 2) height <= specified height (pool.height = current) * 2) height <= specified height (pool.height = current)
* The logic being: if 'now' is after the record activation date
* and 'height' is after the record activation height then
* the record is active
* Remember the active record with the newest activationdate * Remember the active record with the newest activationdate
* If two records have the same activation date, then * If two records have the same activation date, then
* remember the active record with the highest height * remember the active record with the highest height
@ -2197,6 +2200,61 @@ bye:
return ok; return ok;
} }
// The PPS value of a 1diff share for the given workinfoid
double workinfo_pps(K_ITEM *w_item, int64_t workinfoid, bool lock)
{
OPTIONCONTROL *optioncontrol;
K_ITEM *oc_item;
char oc_name[TXT_SML+1];
char coinbase1bin[TXT_SML+1];
char ndiffbin[TXT_SML+1];
WORKINFO *workinfo;
double w_diff;
int w_blocknum;
size_t len;
// Allow optioncontrol override for a given workinfoid
snprintf(oc_name, sizeof(oc_name), PPSOVERRIDE"_%"PRId64, workinfoid);
if (lock)
K_RLOCK(optioncontrol_free);
// No time/height control is used, just find the latest record
oc_item = find_optioncontrol(oc_name, &date_eot, MAX_HEIGHT);
if (lock)
K_RUNLOCK(optioncontrol_free);
// Value is a floating point double of satoshi
if (oc_item) {
DATA_OPTIONCONTROL(optioncontrol, oc_item);
return atof(optioncontrol->optionvalue);
}
if (!w_item) {
LOGERR("%s(): missing workinfo %"PRId64,
__func__, workinfoid);
return 0.0;
}
DATA_WORKINFO(workinfo, w_item);
len = strlen(workinfo->coinbase1);
if (len < (BLOCKNUM_OFFSET * 2 + 4) || (len & 1)) {
LOGERR("%s(): Invalid coinbase1 len %d - "
"should be >= %d and even - for wid %"PRId64,
__func__, (int)len, (BLOCKNUM_OFFSET * 2 + 4),
workinfoid);
return 0.0;
}
hex2bin(ndiffbin, workinfo->bits, 4);
w_diff = diff_from_nbits(ndiffbin);
hex2bin(coinbase1bin, workinfo->coinbase1 + (BLOCKNUM_OFFSET * 2),
(len - (BLOCKNUM_OFFSET * 2)) >> 1);
w_blocknum = get_sernumber((uchar *)coinbase1bin);
// BASE halving to determine coinbase reward then divided by difficulty
return(REWARD_BASE * pow(0.5, floor((double)w_blocknum / REWARD_HALVE)) / w_diff);
}
// order by workinfoid asc,userid asc,workername asc,createdate asc,nonce asc,expirydate desc // order by workinfoid asc,userid asc,workername asc,createdate asc,nonce asc,expirydate desc
cmp_t cmp_shares(K_ITEM *a, K_ITEM *b) cmp_t cmp_shares(K_ITEM *a, K_ITEM *b)
{ {
@ -4767,6 +4825,10 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
K_ITEM *wm_item; K_ITEM *wm_item;
WORKMARKERS *wm; WORKMARKERS *wm;
bool did_one = false; bool did_one = false;
double payout_pps;
payout_pps = (double)delta * (double)(payouts->minerreward) /
payouts->diffused;
if (lock) if (lock)
K_WLOCK(workmarkers_free); K_WLOCK(workmarkers_free);
@ -4781,6 +4843,7 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
* onto the PROCESSED status if it isn't already processed */ * onto the PROCESSED status if it isn't already processed */
if (CURRENT(&(wm->expirydate))) { if (CURRENT(&(wm->expirydate))) {
wm->rewards += delta; wm->rewards += delta;
wm->rewarded += payout_pps;
did_one = true; did_one = true;
} }
wm_item = next_in_ktree(ctx); wm_item = next_in_ktree(ctx);
@ -4792,7 +4855,13 @@ bool reward_shifts(PAYOUTS *payouts, bool lock, int delta)
return did_one; return did_one;
} }
// (re)calculate rewards for a shift /* (re)calculate rewards for a shift
* N.B. we don't need to zero/undo a workmarkers rewards directly
* since this is just a counter of how many times it's been rewarded
* and thus if the shift is expired the counter is ignored
* We only need to (re)calculate it when the workmarker is created
* Payouts code processing will increment/decrement all current rewards as
* needed with reward_shifts() when payouts are added/changed/removed */
bool shift_rewards(K_ITEM *wm_item) bool shift_rewards(K_ITEM *wm_item)
{ {
PAYOUTS *payouts = NULL; PAYOUTS *payouts = NULL;

17
src/ckdb_dbio.c

@ -6628,12 +6628,13 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add,
WHERE_FFL_PASS); WHERE_FFL_PASS);
goto rollback; goto rollback;
} }
w_item = find_workinfo(workinfoidend, NULL); w_item = find_workinfo(workinfoidstart, NULL);
if (!w_item) if (!w_item)
goto rollback; goto rollback;
w_item = find_workinfo(workinfoidstart, NULL); w_item = find_workinfo(workinfoidend, NULL);
if (!w_item) if (!w_item)
goto rollback; goto rollback;
K_WLOCK(workmarkers_free); K_WLOCK(workmarkers_free);
wm_item = k_unlink_head(workmarkers_free); wm_item = k_unlink_head(workmarkers_free);
K_WUNLOCK(workmarkers_free); K_WUNLOCK(workmarkers_free);
@ -6698,6 +6699,7 @@ bool _workmarkers_process(PGconn *conn, bool already, bool add,
PGLOGERR("Insert", rescode, conn); PGLOGERR("Insert", rescode, conn);
goto rollback; goto rollback;
} }
row->pps_value = workinfo_pps(w_item, workinfoidend, true);
} }
ok = true; ok = true;
@ -6837,9 +6839,18 @@ bool workmarkers_fill(PGconn *conn)
add_to_ktree(workmarkers_workinfoid_root, item); add_to_ktree(workmarkers_workinfoid_root, item);
k_add_head(workmarkers_store, item); k_add_head(workmarkers_store, item);
wi_item = find_workinfo(row->workinfoidend, NULL);
if (!wi_item) {
LOGERR("%s(): ERROR workmarkerid %"PRId64
" wid end %"PRId64" doesn't exist! "
"PPS value will be zero",
__func__, row->markerid,
row->workinfoidend);
}
row->pps_value = workinfo_pps(wi_item, row->workinfoidend, false);
if (dbstatus.newest_workmarker_workinfoid < row->workinfoidend) { if (dbstatus.newest_workmarker_workinfoid < row->workinfoidend) {
dbstatus.newest_workmarker_workinfoid = row->workinfoidend; dbstatus.newest_workmarker_workinfoid = row->workinfoidend;
wi_item = find_workinfo(row->workinfoidend, NULL);
if (!wi_item) { if (!wi_item) {
LOGEMERG("%s(): FAILURE workmarkerid %"PRId64 LOGEMERG("%s(): FAILURE workmarkerid %"PRId64
" wid end %"PRId64" doesn't exist! " " wid end %"PRId64" doesn't exist! "

Loading…
Cancel
Save