From 64d8d8abf32c9a89ca1039df3eff1358e9b639f8 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 21:37:14 +0200 Subject: [PATCH 01/10] Adding support for PPS payout method This commit changed a few things in the backend and classes code: * Any _PPS transaction does NOT need to be confirmed * Queries updated for added _PPS transactions * Template updated to properly display these transactions Cronjob * Added pps_payput cron to run payouts based on worker submitted shares * **IMPORTANT**: Can NOT be run with proportional_payout! Addresses #70 --- cronjobs/pps_payout.php | 87 +++++++++++++++++++ public/include/classes/share.class.php | 15 ++++ public/include/classes/transaction.class.php | 18 ++-- .../mmcFE/account/transactions/default.tpl | 5 +- 4 files changed, 118 insertions(+), 7 deletions(-) create mode 100755 cronjobs/pps_payout.php diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php new file mode 100755 index 00000000..a71c42a3 --- /dev/null +++ b/cronjobs/pps_payout.php @@ -0,0 +1,87 @@ +#!/usr/bin/php +can_connect() === true ){ + $dDifficulty = $bitcoin->getdifficulty(); +} else { + verbose("Aborted: " . $bitcoin->can_connect() . "\n"); + exit(1); +} + +// Value per share calculation +$pps_value = 50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']); + +// Find our last share accounted and last inserted share for PPS calculations +$iPreviousShareId = $setting->getValue('pps_last_share_id'); +$iLastShareId = $share->getLastInsertedShareId(); + +// Check for all new shares, we start one higher as our last accounted share to avoid duplicates +$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId); + +verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\t\tStatus\n"); + +foreach ($aAccountShares as $aData) { + // Take our valid shares and multiply by per share value + $aData['payout'] = $aData['valid'] * $pps_value; + + // Defaults + $aData['fee' ] = 0; + $aData['donation'] = 0; + + // Calculate block fees + if ($config['fees'] > 0) + $aData['fee'] = number_format(round($config['fees'] / 100 * $aData['payout'], 8), 8); + // Calculate donation amount + $aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8); + + verbose($aData['id'] . "\t" . + $aData['username'] . "\t" . + $aData['invalid'] . "\t" . + $aData['valid'] . "\t*\t" . + $pps_value . "\t=\t" . + $aData['payout'] . "\t" . + $aData['donation'] . "\t" . + $aData['fee'] . "\t"); + + $strStatus = "OK"; + // Add new credit transaction + if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS')) + $strStatus = "Transaction Failed"; + // Add new fee debit for this block + if ($aData['fee'] > 0 && $config['fees'] > 0) + if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS')) + $strStatus = "Fee Failed"; + // Add new donation debit + if ($aData['donation'] > 0) + if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS')) + $strStatus = "Donation Failed"; + verbose($strStatus . "\n"); +} + +// Store our last inserted ID for the next run +$setting->setValue('pps_last_share_id', $iLastShareId); + +verbose("\n\n------------------------------------------------------------------------------------\n\n"); +?> diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index b0a3b249..1033f92c 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -44,6 +44,21 @@ class Share { return $this->table; } + /** + * Get last inserted Share ID from Database + * Used for PPS calculations without moving to archive + **/ + public function getLastInsertedShareId() { + $stmt = $this->mysqli->prepare(" + SELECT MAX(id) AS id FROM $this->table + "); + if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_object()->id; + // Catchall + $this->setErrorMessage('Failed to fetch last inserted share ID'); + return false; + } + /** * Get all valid shares for this round * @param previous_upstream int Previous found share accepted by upstream to limit results diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 020140d3..711e893f 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -142,7 +142,7 @@ class Transaction { ( SELECT sum(t.amount) AS credit FROM $this->table AS t - WHERE t.type = 'Credit' + WHERE t.type IN ('Credit', 'Credit_PPS') ) AS t1, ( SELECT sum(t.amount) AS debit @@ -152,7 +152,7 @@ class Transaction { ( SELECT sum(t.amount) AS other FROM " . $this->table . " AS t - WHERE t.type IN ('Donation','Fee') + WHERE t.type IN ('Donation','Fee','Donation_PPS','Fee_PPS') ) AS t3"); if ($this->checkStmt($stmt) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch()) return $dBalance; @@ -176,8 +176,11 @@ class Transaction { SELECT sum(t.amount) AS credit FROM $this->table AS t LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id - WHERE t.type = 'Credit' - AND b.confirmations >= ? + WHERE + ( + ( t.type = 'Credit' AND b.confirmations >= ? ) OR + ( t.type = 'Credit_PPS' ) + ) AND t.account_id = ? ) AS t1, ( @@ -190,8 +193,11 @@ class Transaction { SELECT sum(t.amount) AS other FROM $this->table AS t LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id - WHERE t.type IN ('Donation','Fee') - AND b.confirmations >= ? + WHERE + ( + ( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR + ( t.type IN ('Donation_PPS', 'Fee_PPS') ) + ) AND t.account_id = ? ) AS t3 "); diff --git a/public/templates/mmcFE/account/transactions/default.tpl b/public/templates/mmcFE/account/transactions/default.tpl index 8f5282e1..dd31723f 100644 --- a/public/templates/mmcFE/account/transactions/default.tpl +++ b/public/templates/mmcFE/account/transactions/default.tpl @@ -18,6 +18,9 @@ ($TRANSACTIONS[transaction].type == 'Credit' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) + or $TRANSACTIONS[transaction].type == 'Credit_PPS' + or $TRANSACTIONS[transaction].type == 'Fee_PPS' + or $TRANSACTIONS[transaction].type == 'Donation_PPS' or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_MP' )} @@ -27,7 +30,7 @@ {$TRANSACTIONS[transaction].type} {$TRANSACTIONS[transaction].coin_address} {if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if} - {$TRANSACTIONS[transaction].amount} + {$TRANSACTIONS[transaction].amount} {/if} {/section} From a3ddf0cfcca9b80a1e3e4d4c434f53fe1653eb6a Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:31:35 +0200 Subject: [PATCH 02/10] properly format payout and round it --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index a71c42a3..1dafa288 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -44,7 +44,7 @@ verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\ foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value - $aData['payout'] = $aData['valid'] * $pps_value; + $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8)); // Defaults $aData['fee' ] = 0; From ad6051df1c0682addb4edebca39c414edee99b15 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:34:02 +0200 Subject: [PATCH 03/10] forgot 8 decimals --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index 1dafa288..bef78f2a 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -44,7 +44,7 @@ verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\ foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value - $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8)); + $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8), 8); // Defaults $aData['fee' ] = 0; From 663c427d4adaf8d96d51e98024c1dd19e83187e4 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:45:53 +0200 Subject: [PATCH 04/10] properly format pps value to 12 digits --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index bef78f2a..e2804595 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -31,7 +31,7 @@ if ( $bitcoin->can_connect() === true ){ } // Value per share calculation -$pps_value = 50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']); +$pps_value = number_format(round(50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12); // Find our last share accounted and last inserted share for PPS calculations $iPreviousShareId = $setting->getValue('pps_last_share_id'); From 87e721edb89429c2d96af17858d83e8712e9339d Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:48:09 +0200 Subject: [PATCH 05/10] moved table header to the left --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index e2804595..427035d5 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -40,7 +40,7 @@ $iLastShareId = $share->getLastInsertedShareId(); // Check for all new shares, we start one higher as our last accounted share to avoid duplicates $aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId); -verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\t\tStatus\n"); +verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee\t\tStatus\n"); foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value From 531e28cee85f9b96136cfe128f8cfaf4860ee68b Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 21:37:14 +0200 Subject: [PATCH 06/10] Adding support for PPS payout method This commit changed a few things in the backend and classes code: * Any _PPS transaction does NOT need to be confirmed * Queries updated for added _PPS transactions * Template updated to properly display these transactions Cronjob * Added pps_payput cron to run payouts based on worker submitted shares * **IMPORTANT**: Can NOT be run with proportional_payout! Addresses #70 --- cronjobs/pps_payout.php | 87 +++++++++++++++++++ public/include/classes/share.class.php | 15 ++++ public/include/classes/transaction.class.php | 18 ++-- .../mmcFE/account/transactions/default.tpl | 5 +- 4 files changed, 118 insertions(+), 7 deletions(-) create mode 100755 cronjobs/pps_payout.php diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php new file mode 100755 index 00000000..a71c42a3 --- /dev/null +++ b/cronjobs/pps_payout.php @@ -0,0 +1,87 @@ +#!/usr/bin/php +can_connect() === true ){ + $dDifficulty = $bitcoin->getdifficulty(); +} else { + verbose("Aborted: " . $bitcoin->can_connect() . "\n"); + exit(1); +} + +// Value per share calculation +$pps_value = 50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']); + +// Find our last share accounted and last inserted share for PPS calculations +$iPreviousShareId = $setting->getValue('pps_last_share_id'); +$iLastShareId = $share->getLastInsertedShareId(); + +// Check for all new shares, we start one higher as our last accounted share to avoid duplicates +$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId); + +verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\t\tStatus\n"); + +foreach ($aAccountShares as $aData) { + // Take our valid shares and multiply by per share value + $aData['payout'] = $aData['valid'] * $pps_value; + + // Defaults + $aData['fee' ] = 0; + $aData['donation'] = 0; + + // Calculate block fees + if ($config['fees'] > 0) + $aData['fee'] = number_format(round($config['fees'] / 100 * $aData['payout'], 8), 8); + // Calculate donation amount + $aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8); + + verbose($aData['id'] . "\t" . + $aData['username'] . "\t" . + $aData['invalid'] . "\t" . + $aData['valid'] . "\t*\t" . + $pps_value . "\t=\t" . + $aData['payout'] . "\t" . + $aData['donation'] . "\t" . + $aData['fee'] . "\t"); + + $strStatus = "OK"; + // Add new credit transaction + if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS')) + $strStatus = "Transaction Failed"; + // Add new fee debit for this block + if ($aData['fee'] > 0 && $config['fees'] > 0) + if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS')) + $strStatus = "Fee Failed"; + // Add new donation debit + if ($aData['donation'] > 0) + if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS')) + $strStatus = "Donation Failed"; + verbose($strStatus . "\n"); +} + +// Store our last inserted ID for the next run +$setting->setValue('pps_last_share_id', $iLastShareId); + +verbose("\n\n------------------------------------------------------------------------------------\n\n"); +?> diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index b0a3b249..1033f92c 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -44,6 +44,21 @@ class Share { return $this->table; } + /** + * Get last inserted Share ID from Database + * Used for PPS calculations without moving to archive + **/ + public function getLastInsertedShareId() { + $stmt = $this->mysqli->prepare(" + SELECT MAX(id) AS id FROM $this->table + "); + if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) + return $result->fetch_object()->id; + // Catchall + $this->setErrorMessage('Failed to fetch last inserted share ID'); + return false; + } + /** * Get all valid shares for this round * @param previous_upstream int Previous found share accepted by upstream to limit results diff --git a/public/include/classes/transaction.class.php b/public/include/classes/transaction.class.php index 020140d3..711e893f 100644 --- a/public/include/classes/transaction.class.php +++ b/public/include/classes/transaction.class.php @@ -142,7 +142,7 @@ class Transaction { ( SELECT sum(t.amount) AS credit FROM $this->table AS t - WHERE t.type = 'Credit' + WHERE t.type IN ('Credit', 'Credit_PPS') ) AS t1, ( SELECT sum(t.amount) AS debit @@ -152,7 +152,7 @@ class Transaction { ( SELECT sum(t.amount) AS other FROM " . $this->table . " AS t - WHERE t.type IN ('Donation','Fee') + WHERE t.type IN ('Donation','Fee','Donation_PPS','Fee_PPS') ) AS t3"); if ($this->checkStmt($stmt) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch()) return $dBalance; @@ -176,8 +176,11 @@ class Transaction { SELECT sum(t.amount) AS credit FROM $this->table AS t LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id - WHERE t.type = 'Credit' - AND b.confirmations >= ? + WHERE + ( + ( t.type = 'Credit' AND b.confirmations >= ? ) OR + ( t.type = 'Credit_PPS' ) + ) AND t.account_id = ? ) AS t1, ( @@ -190,8 +193,11 @@ class Transaction { SELECT sum(t.amount) AS other FROM $this->table AS t LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id - WHERE t.type IN ('Donation','Fee') - AND b.confirmations >= ? + WHERE + ( + ( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR + ( t.type IN ('Donation_PPS', 'Fee_PPS') ) + ) AND t.account_id = ? ) AS t3 "); diff --git a/public/templates/mmcFE/account/transactions/default.tpl b/public/templates/mmcFE/account/transactions/default.tpl index 8f5282e1..dd31723f 100644 --- a/public/templates/mmcFE/account/transactions/default.tpl +++ b/public/templates/mmcFE/account/transactions/default.tpl @@ -18,6 +18,9 @@ ($TRANSACTIONS[transaction].type == 'Credit' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) + or $TRANSACTIONS[transaction].type == 'Credit_PPS' + or $TRANSACTIONS[transaction].type == 'Fee_PPS' + or $TRANSACTIONS[transaction].type == 'Donation_PPS' or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_MP' )} @@ -27,7 +30,7 @@ {$TRANSACTIONS[transaction].type} {$TRANSACTIONS[transaction].coin_address} {if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if} - {$TRANSACTIONS[transaction].amount} + {$TRANSACTIONS[transaction].amount} {/if} {/section} From dcfbd83270292261e2a0c57964055a6feb57faa8 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:31:35 +0200 Subject: [PATCH 07/10] properly format payout and round it --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index a71c42a3..1dafa288 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -44,7 +44,7 @@ verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\ foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value - $aData['payout'] = $aData['valid'] * $pps_value; + $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8)); // Defaults $aData['fee' ] = 0; From 5f1e52767e88db2dd8dff843b8463b8b2a9b8ca5 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:34:02 +0200 Subject: [PATCH 08/10] forgot 8 decimals --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index 1dafa288..bef78f2a 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -44,7 +44,7 @@ verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\ foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value - $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8)); + $aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8), 8); // Defaults $aData['fee' ] = 0; From 4a36479fe22205d959e80e17e314da294aa5adbe Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:45:53 +0200 Subject: [PATCH 09/10] properly format pps value to 12 digits --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index bef78f2a..e2804595 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -31,7 +31,7 @@ if ( $bitcoin->can_connect() === true ){ } // Value per share calculation -$pps_value = 50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']); +$pps_value = number_format(round(50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12); // Find our last share accounted and last inserted share for PPS calculations $iPreviousShareId = $setting->getValue('pps_last_share_id'); From b6da195da5954e790d5deb521d2a090094a2c2ef Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Thu, 6 Jun 2013 23:48:09 +0200 Subject: [PATCH 10/10] moved table header to the left --- cronjobs/pps_payout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cronjobs/pps_payout.php b/cronjobs/pps_payout.php index e2804595..427035d5 100755 --- a/cronjobs/pps_payout.php +++ b/cronjobs/pps_payout.php @@ -40,7 +40,7 @@ $iLastShareId = $share->getLastInsertedShareId(); // Check for all new shares, we start one higher as our last accounted share to avoid duplicates $aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId); -verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\t\tPayout\t\tDonation\tFee\t\tStatus\n"); +verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee\t\tStatus\n"); foreach ($aAccountShares as $aData) { // Take our valid shares and multiply by per share value