Skip to content

Commit db89768

Browse files
committed
Merge pull request #648 from TheSerapher/issue-145
Issue 145
2 parents e34ff26 + 432f2b1 commit db89768

File tree

20 files changed

+235
-88
lines changed

20 files changed

+235
-88
lines changed

cronjobs/pplns_payout.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
if ($config['pplns']['shares']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
4949
$pplns_target = round($block->getAvgBlockShares($config['pplns']['blockavg']['blockcount']));
5050
} else {
51-
$pplns_target = $config['pplns']['shares']['default'] ;
51+
$pplns_target = $config['pplns']['shares']['default'];
5252
}
5353

5454
if (!$aBlock['accounted']) {
@@ -68,16 +68,21 @@
6868

6969
if ($iRoundShares >= $pplns_target) {
7070
$log->logDebug("Matching or exceeding PPLNS target of $pplns_target with $iRoundShares");
71-
$aAccountShares = $share->getSharesForAccounts($aBlock['share_id'] - $pplns_target, $aBlock['share_id']);
71+
$iMinimumShareId = $share->getMinimumShareId($pplns_target, $aBlock['share_id']);
72+
// We need to go one ID lower due to `id >` or we won't match if minimum share ID == $aBlock['share_id']
73+
$aAccountShares = $share->getSharesForAccounts($iMinimumShareId - 1, $aBlock['share_id']);
7274
if (empty($aAccountShares)) {
7375
$log->logFatal("No shares found for this block, aborted! Block Height : " . $aBlock['height']);
7476
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
7577
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block: " . $aBlock['height']);
7678
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
7779
exit(1);
7880
}
79-
$log->logInfo('Adjusting round target to PPLNS target ' . $pplns_target);
80-
$iRoundShares = $pplns_target;
81+
foreach($aAccountShares as $key => $aData) {
82+
$iNewRoundShares += $aData['valid'];
83+
}
84+
$log->logInfo('Adjusting round target to PPLNS target ' . $iNewRoundShares);
85+
$iRoundShares = $iNewRoundShares;
8186
} else {
8287
$log->logDebug("Not able to match PPLNS target of $pplns_target with $iRoundShares");
8388
// We need to fill up with archived shares
@@ -156,6 +161,7 @@
156161
if (!$statistics->updateShareStatistics($aRoundData, $aBlock['id']))
157162
$log->logError('Failed to update share statistics for ' . $aData['username']);
158163
}
164+
159165
// Add new credit transaction
160166
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
161167
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);

cronjobs/pps_payout.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,29 @@
4545
exit(1);
4646
}
4747

48-
// Value per share calculation
49-
if ($config['reward_type'] != 'block') {
50-
$pps_value = round($config['reward'] / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12);
48+
// We support some dynamic reward targets but fall back to our fixed value
49+
// Re-calculate after each run due to re-targets in this loop
50+
if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
51+
$pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount']));
52+
$log->logInfo("PPS reward using block average, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
5153
} else {
52-
// Try to find the last block value and use that for future payouts, revert to fixed reward if none found
53-
if ($aLastBlock = $block->getLast()) {
54-
$pps_value = round($aLastBlock['amount'] / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12);
54+
if ($config['pps']['reward']['type'] == 'block') {
55+
if ($aLastBlock = $block->getLast()) {
56+
$pps_reward = $aLastBlock['amount'];
57+
$log->logInfo("PPS reward using last block, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
58+
} else {
59+
$pps_reward = $config['pps']['reward']['default'];
60+
$log->logInfo("PPS reward using default, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
61+
}
5562
} else {
56-
$pps_value = round($config['reward'] / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12);
63+
$pps_reward = $config['pps']['reward']['default'];
64+
$log->logInfo("PPS reward fixed default, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
5765
}
5866
}
5967

68+
// Per-share value to be paid out to users
69+
$pps_value = round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12);
70+
6071
// Find our last share accounted and last inserted share for PPS calculations
6172
$iPreviousShareId = $setting->getValue('pps_last_share_id');
6273
$iLastShareId = $share->getLastInsertedShareId();
@@ -87,7 +98,7 @@
8798
number_format($pps_value, 12) . "\t=\t" .
8899
number_format($aData['payout'], 8) . "\t" .
89100
number_format($aData['donation'], 8) . "\t" .
90-
number_format($aData['fee']), 8);
101+
number_format($aData['fee'], 8));
91102

92103
// Add new credit transaction
93104
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
@@ -107,9 +118,7 @@
107118

108119
// Fetch all unaccounted blocks
109120
$aAllBlocks = $block->getAllUnaccounted('ASC');
110-
if (empty($aAllBlocks)) {
111-
$log->logDebug("No new unaccounted blocks found");
112-
}
121+
if (empty($aAllBlocks)) $log->logDebug("No new unaccounted blocks found");
113122

114123
// Go through blocks and archive/delete shares that have been accounted for
115124
foreach ($aAllBlocks as $iIndex => $aBlock) {

public/include/classes/block.class.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,18 @@ public function getAvgBlockShares($limit=1) {
116116
return false;
117117
}
118118

119+
/**
120+
* Fetch our average rewards for the past N blocks
121+
* @param limit int Maximum blocks to check
122+
* @return data float Float value of average shares
123+
**/
124+
public function getAvgBlockReward($limit=1) {
125+
$stmt = $this->mysqli->prepare("SELECT AVG(x.amount) AS average FROM (SELECT amount FROM $this->table ORDER BY height DESC LIMIT ?) AS x");
126+
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $limit) && $stmt->execute() && $result = $stmt->get_result())
127+
return (float)$result->fetch_object()->average;
128+
return false;
129+
}
130+
119131
/**
120132
* Fetch all unconfirmed blocks from table
121133
* @param confirmations int Required confirmations to consider block confirmed

public/include/classes/share.class.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Share {
1111
private $oUpstream;
1212
private $iLastUpstreamId;
1313
// This defines each share
14-
public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time;
14+
public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time, $difficulty;
1515

1616
public function __construct($debug, $mysqli, $user, $block, $config) {
1717
$this->debug = $debug;
@@ -70,7 +70,7 @@ public function getLastInsertedShareId() {
7070
**/
7171
public function getRoundShares($previous_upstream=0, $current_upstream) {
7272
$stmt = $this->mysqli->prepare("SELECT
73-
count(id) as total
73+
ROUND(IFNULL(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 8) AS total
7474
FROM $this->table
7575
WHERE our_result = 'Y'
7676
AND id > ? AND id <= ?
@@ -98,8 +98,8 @@ public function getSharesForAccounts($previous_upstream=0, $current_upstream) {
9898
a.id,
9999
SUBSTRING_INDEX( s.username , '.', 1 ) as username,
100100
a.no_fees AS no_fees,
101-
IFNULL(SUM(IF(our_result='Y', 1, 0)), 0) AS valid,
102-
IFNULL(SUM(IF(our_result='N', 1, 0)), 0) AS invalid
101+
ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 8) AS valid,
102+
ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 8) AS invalid
103103
FROM $this->table AS s
104104
LEFT JOIN " . $this->user->getTableName() . " AS a
105105
ON a.username = SUBSTRING_INDEX( s.username , '.', 1 )
@@ -140,15 +140,15 @@ function getMaxArchiveShareId() {
140140
* return array data Returns an array with usernames as keys for easy access
141141
**/
142142
function getArchiveShares($iCount) {
143-
$iMinId = $this->getMaxArchiveShareId() - $iCount;
143+
$iMinId = $this->getMinArchiveShareId($iCount);
144144
$iMaxId = $this->getMaxArchiveShareId();
145145
$stmt = $this->mysqli->prepare("
146146
SELECT
147147
a.id,
148148
SUBSTRING_INDEX( s.username , '.', 1 ) as account,
149149
a.no_fees AS no_fees,
150-
IFNULL(SUM(IF(our_result='Y', 1, 0)), 0) AS valid,
151-
IFNULL(SUM(IF(our_result='N', 1, 0)), 0) AS invalid
150+
ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 8) AS valid,
151+
ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 8) AS invalid
152152
FROM $this->tableArchive AS s
153153
LEFT JOIN " . $this->user->getTableName() . " AS a
154154
ON a.username = SUBSTRING_INDEX( s.username , '.', 1 )
@@ -198,8 +198,8 @@ public function purgeArchive() {
198198
**/
199199
public function moveArchive($current_upstream, $block_id, $previous_upstream=0) {
200200
$archive_stmt = $this->mysqli->prepare("
201-
INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time)
202-
SELECT id, username, our_result, upstream_result, ?, time
201+
INSERT INTO $this->tableArchive (share_id, username, our_result, upstream_result, block_id, time, difficulty)
202+
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
203203
FROM $this->table
204204
WHERE id > ? AND id <= ?");
205205
if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute()) {
@@ -317,6 +317,48 @@ public function setUpstream($aBlock, $last=0) {
317317
return false;
318318
}
319319

320+
/**
321+
* Fetch the lowest needed share ID from shares
322+
**/
323+
function getMinimumShareId($iCount, $current_upstream) {
324+
// We don't use baseline here to be more accurate
325+
$iCount = $iCount * pow(2, ($this->config['difficulty'] - 16));
326+
$stmt = $this->mysqli->prepare("
327+
SELECT MIN(b.id) AS id FROM
328+
(
329+
SELECT id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total
330+
FROM $this->table, (SELECT @total := 0) AS a
331+
WHERE our_result = 'Y'
332+
AND id <= ? AND @total < ?
333+
ORDER BY id DESC
334+
) AS b
335+
WHERE total <= ?
336+
");
337+
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $current_upstream, $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
338+
return $result->fetch_object()->id;
339+
return false;
340+
}
341+
342+
/**
343+
* Fetch the lowest needed share ID from archive
344+
**/
345+
function getMinArchiveShareId($iCount) {
346+
$stmt = $this->mysqli->prepare("
347+
SELECT MIN(b.share_id) AS share_id FROM
348+
(
349+
SELECT share_id, @total := @total + (IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) / POW(2, (" . $this->config['difficulty'] . " - 16))) AS total
350+
FROM $this->tableArchive, (SELECT @total := 0) AS a
351+
WHERE our_result = 'Y'
352+
AND @total < ?
353+
ORDER BY share_id DESC
354+
) AS b
355+
WHERE total <= ?
356+
");
357+
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
358+
return $result->fetch_object()->share_id;
359+
return false;
360+
}
361+
320362
/**
321363
* Helper function
322364
**/

0 commit comments

Comments
 (0)