3
.gitignore
vendored
@ -3,3 +3,6 @@
|
|||||||
/cronjobs/logs/*.txt
|
/cronjobs/logs/*.txt
|
||||||
/cronjobs/logs/*.txt.*.gz
|
/cronjobs/logs/*.txt.*.gz
|
||||||
/public/templates/cache/*.php
|
/public/templates/cache/*.php
|
||||||
|
# Test configs
|
||||||
|
public/include/config/global.inc.scrypt.php
|
||||||
|
public/include/config/global.inc.sha.php
|
||||||
|
|||||||
27
README.md
@ -5,7 +5,7 @@ MPOS is a web based Mining Portal for various crypto currencies. A few pools usi
|
|||||||
|
|
||||||
* http://ltc.pool.grewe.ca
|
* http://ltc.pool.grewe.ca
|
||||||
* http://fst.pool.grewe.ca
|
* http://fst.pool.grewe.ca
|
||||||
* http://nvc.pool.grewe.ca
|
* http://ftc.pool.grewe.ca
|
||||||
|
|
||||||
**NOTE**: This project is still under development and commits are happening on a daily basis.
|
**NOTE**: This project is still under development and commits are happening on a daily basis.
|
||||||
I do not recommend using this for a live setup as of yet. Wait for the later Release Candidate
|
I do not recommend using this for a live setup as of yet. Wait for the later Release Candidate
|
||||||
@ -18,11 +18,7 @@ I was hoping to keep this out of the README but apparently people remove or chan
|
|||||||
at the bottom of the page. For those of you finding my project and are willing to appreciate the work
|
at the bottom of the page. For those of you finding my project and are willing to appreciate the work
|
||||||
with some hard earned coins feel free to donate:
|
with some hard earned coins feel free to donate:
|
||||||
|
|
||||||
* BTC address: `1HuYK6WPU8o3yWCrAaADDZPRpL5QiXitfv`
|
|
||||||
* LTC address: `Lge95QR2frp9y1wJufjUPCycVsg5gLJPW8`
|
* LTC address: `Lge95QR2frp9y1wJufjUPCycVsg5gLJPW8`
|
||||||
* FTC address: `6jDgGaUzMVyac5uqBhJCMiFMKCtH1LagTA`
|
|
||||||
* NVC address: `4Guct6z7NVPVALHRAVn517TTmvqQve4WYr`
|
|
||||||
* FST address: `g17CfFHqNqR5JnUjtG8RNBYh2WrhEirV67`
|
|
||||||
|
|
||||||
Website Footer
|
Website Footer
|
||||||
==============
|
==============
|
||||||
@ -50,8 +46,6 @@ Requirements
|
|||||||
|
|
||||||
This setup has been tested on Ubuntu 12.04, Ubuntu 13.04 and CentOS.
|
This setup has been tested on Ubuntu 12.04, Ubuntu 13.04 and CentOS.
|
||||||
It should also work on any related distribution (RHEL, Debian).
|
It should also work on any related distribution (RHEL, Debian).
|
||||||
For support on how to get `litecoind` or `pushpoold` to work, please ask
|
|
||||||
in the appropriate forums.
|
|
||||||
|
|
||||||
Be aware that `MPOS` is **only** for pooled mining. Solo Mining is not
|
Be aware that `MPOS` is **only** for pooled mining. Solo Mining is not
|
||||||
supported. They will never match an upstream share, solo miners do not create
|
supported. They will never match an upstream share, solo miners do not create
|
||||||
@ -77,16 +71,16 @@ The following feature have been implemented so far:
|
|||||||
|
|
||||||
* Fully re-written GUI with [Smarty][2] templates
|
* Fully re-written GUI with [Smarty][2] templates
|
||||||
* Mobile WebUI
|
* Mobile WebUI
|
||||||
* **NEW** VARDIFF Support
|
* Scrypt, **NEW** SHA256, VARDIFF Support
|
||||||
* Reward Systems
|
* Reward Systems
|
||||||
* Propotional
|
* Propotional
|
||||||
* PPS
|
* PPS
|
||||||
* PPLNS
|
* PPLNS
|
||||||
* Statistics are cached in Memcache by Cronjob for quick data access
|
* Statistics are cached in Memcache by Cronjob for quick data access
|
||||||
* **NEW** New Theme
|
* New Theme
|
||||||
* **NEW** Live Dashboard
|
* Live Dashboard
|
||||||
* **NEW** AJAX Support
|
* AJAX Support
|
||||||
* **NEW** Overhauled API
|
* Overhauled API
|
||||||
* Web User accounts
|
* Web User accounts
|
||||||
* Re-Captcha protected registration form
|
* Re-Captcha protected registration form
|
||||||
* Worker accounts
|
* Worker accounts
|
||||||
@ -143,6 +137,15 @@ Other customizations are also possible but will require merging changes together
|
|||||||
on non-existing features in `MPOS`. For the vast majority, adjusting themes should be enough to highlight your pool from others.
|
on non-existing features in `MPOS`. For the vast majority, adjusting themes should be enough to highlight your pool from others.
|
||||||
|
|
||||||
In all that, I humbly ask to keep the `MPOS` author reference and Github URL intact.
|
In all that, I humbly ask to keep the `MPOS` author reference and Github URL intact.
|
||||||
|
|
||||||
|
Related Software
|
||||||
|
================
|
||||||
|
|
||||||
|
There are a few other projects out there that take advantage of MPOS and it's included API. Here a quick list that you can check out for yourself:
|
||||||
|
|
||||||
|
* [MPOS IRC Bot](https://github.com/WKNiGHT-/mpos-bot) written in Python, standlone bot, using the MPOS API
|
||||||
|
* [MPOS Eggdrop Module](https://github.com/iAmShorty/mpos-eggdrop-tcl) written in TCL, adding MPOS commands to this bot, using the MPOS API
|
||||||
|
|
||||||
Contributing
|
Contributing
|
||||||
============
|
============
|
||||||
|
|
||||||
|
|||||||
@ -28,10 +28,7 @@ require_once('shared.inc.php');
|
|||||||
// If we don't keep archives, delete some now to release disk space
|
// If we don't keep archives, delete some now to release disk space
|
||||||
if (!$share->purgeArchive()) {
|
if (!$share->purgeArchive()) {
|
||||||
$log->logError("Failed to delete archived shares, not critical but should be checked!");
|
$log->logError("Failed to delete archived shares, not critical but should be checked!");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0008', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete archived shares");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cron cleanup and monitoring
|
// Cron cleanup and monitoring
|
||||||
|
|||||||
@ -27,19 +27,12 @@ require_once('shared.inc.php');
|
|||||||
|
|
||||||
if ($setting->getValue('disable_ap') == 1) {
|
if ($setting->getValue('disable_ap') == 1) {
|
||||||
$log->logInfo(" auto payout disabled via admin panel");
|
$log->logInfo(" auto payout disabled via admin panel");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0009', 0, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Auto-Payout disabled");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
$monitoring->setStatus($cron_name . "_endtime", "date", time());
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bitcoin->can_connect() !== true) {
|
if ($bitcoin->can_connect() !== true) {
|
||||||
$log->logFatal(" unable to connect to RPC server, exiting");
|
$log->logFatal(" unable to connect to RPC server, exiting");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0006', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all users with setup AP
|
// Fetch all users with setup AP
|
||||||
@ -73,14 +66,14 @@ if (! empty($users)) {
|
|||||||
|
|
||||||
// Send balance, fees are reduced later by RPC Server
|
// Send balance, fees are reduced later by RPC Server
|
||||||
try {
|
try {
|
||||||
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - $config['txfee']);
|
$txid = $bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - $config['txfee']);
|
||||||
} catch (BitcoinClientException $e) {
|
} catch (BitcoinClientException $e) {
|
||||||
$log->logError('Failed to send requested balance to coin address, please check payout process');
|
$log->logError('Failed to send requested balance to coin address, please check payout process');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create transaction record
|
// Create transaction record
|
||||||
if ($transaction->addTransaction($aUserData['id'], $dBalance - $config['txfee'], 'Debit_AP', NULL, $aUserData['coin_address']) && $transaction->addTransaction($aUserData['id'], $config['txfee'], 'TXFee', NULL, $aUserData['coin_address'])) {
|
if ($transaction->addTransaction($aUserData['id'], $dBalance - $config['txfee'], 'Debit_AP', NULL, $aUserData['coin_address'], $txid) && $transaction->addTransaction($aUserData['id'], $config['txfee'], 'TXFee', NULL, $aUserData['coin_address'])) {
|
||||||
// Mark all older transactions as archived
|
// Mark all older transactions as archived
|
||||||
if (!$transaction->setArchived($aUserData['id'], $transaction->insert_id))
|
if (!$transaction->setArchived($aUserData['id'], $transaction->insert_id))
|
||||||
$log->logError('Failed to mark transactions for user #' . $aUserData['id'] . ' prior to #' . $transaction->insert_id . ' as archived');
|
$log->logError('Failed to mark transactions for user #' . $aUserData['id'] . ' prior to #' . $transaction->insert_id . ' as archived');
|
||||||
|
|||||||
@ -27,10 +27,7 @@ require_once('shared.inc.php');
|
|||||||
|
|
||||||
if ( $bitcoin->can_connect() !== true ) {
|
if ( $bitcoin->can_connect() !== true ) {
|
||||||
$log->logFatal("Failed to connect to RPC server\n");
|
$log->logFatal("Failed to connect to RPC server\n");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0006', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all unconfirmed blocks
|
// Fetch all unconfirmed blocks
|
||||||
@ -54,7 +51,7 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
if ($aBlock['confirmations'] == $aBlockInfo['confirmations']) {
|
if ($aBlock['confirmations'] == $aBlockInfo['confirmations']) {
|
||||||
$log->logDebug(' No update needed');
|
$log->logDebug(' No update needed');
|
||||||
} else if (!$block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
|
} else if (!$block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
|
||||||
$log->logError(' Failed to update block confirmations');
|
$log->logError(' Failed to update block confirmations: ' . $block->getCronMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Monitoring cleanup and status update
|
// Monitoring cleanup and status update
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "OK");
|
$monitoring->endCronjob($cron_name, 'OK', 0, false, false);
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
|
||||||
$monitoring->setStatus($cron_name . "_runtime", "time", microtime(true) - $cron_start[$cron_name]);
|
$monitoring->setStatus($cron_name . "_runtime", "time", microtime(true) - $cron_start[$cron_name]);
|
||||||
$monitoring->setStatus($cron_name . "_endtime", "date", time());
|
$monitoring->setStatus($cron_name . "_endtime", "date", time());
|
||||||
// Mark cron as running for monitoring
|
|
||||||
$monitoring->setStatus($cron_name . '_active', "yesno", 0);
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -35,10 +35,7 @@ if ( $bitcoin->can_connect() === true ){
|
|||||||
$aTransactions = $bitcoin->query('listsinceblock', $strLastBlockHash);
|
$aTransactions = $bitcoin->query('listsinceblock', $strLastBlockHash);
|
||||||
} else {
|
} else {
|
||||||
$log->logFatal('Unable to conenct to RPC server backend');
|
$log->logFatal('Unable to conenct to RPC server backend');
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0006', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do so bail out
|
// Nothing to do so bail out
|
||||||
@ -51,22 +48,22 @@ if (empty($aTransactions['transactions'])) {
|
|||||||
// Let us add those blocks as unaccounted
|
// Let us add those blocks as unaccounted
|
||||||
foreach ($aTransactions['transactions'] as $iIndex => $aData) {
|
foreach ($aTransactions['transactions'] as $iIndex => $aData) {
|
||||||
if ( $aData['category'] == 'generate' || $aData['category'] == 'immature' ) {
|
if ( $aData['category'] == 'generate' || $aData['category'] == 'immature' ) {
|
||||||
$aBlockInfo = $bitcoin->query('getblock', $aData['blockhash']);
|
$aBlockRPCInfo = $bitcoin->query('getblock', $aData['blockhash']);
|
||||||
$config['reward_type'] == 'block' ? $aData['amount'] = $aData['amount'] : $aData['amount'] = $config['reward'];
|
$config['reward_type'] == 'block' ? $aData['amount'] = $aData['amount'] : $aData['amount'] = $config['reward'];
|
||||||
$aData['height'] = $aBlockInfo['height'];
|
$aData['height'] = $aBlockRPCInfo['height'];
|
||||||
$aData['difficulty'] = $aBlockInfo['difficulty'];
|
$aData['difficulty'] = $aBlockRPCInfo['difficulty'];
|
||||||
$log->logInfo(substr($aData['blockhash'], 0, 15) . "...\t" .
|
$log->logInfo(substr($aData['blockhash'], 0, 15) . "...\t" .
|
||||||
$aData['height'] . "\t" .
|
$aData['height'] . "\t" .
|
||||||
$aData['amount'] . "\t" .
|
$aData['amount'] . "\t" .
|
||||||
$aData['confirmations'] . "\t\t" .
|
$aData['confirmations'] . "\t\t" .
|
||||||
$aData['difficulty'] . "\t" .
|
$aData['difficulty'] . "\t" .
|
||||||
strftime("%Y-%m-%d %H:%M:%S", $aData['time']));
|
strftime("%Y-%m-%d %H:%M:%S", $aData['time']));
|
||||||
if ( ! empty($aBlockInfo['flags']) && preg_match('/proof-of-stake/', $aBlockInfo['flags']) ) {
|
if ( ! empty($aBlockRPCInfo['flags']) && preg_match('/proof-of-stake/', $aBlockRPCInfo['flags']) ) {
|
||||||
$log->logInfo("Block above with height " . $aData['height'] . " not added to database, proof-of-stake block!");
|
$log->logInfo("Block above with height " . $aData['height'] . " not added to database, proof-of-stake block!");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!$block->addBlock($aData) ) {
|
if (!$block->addBlock($aData) ) {
|
||||||
$log->logFatal('Unable to add this block to database: ' . $aData['height']);
|
$log->logFatal('Unable to add block: ' . $aData['height'] . ': ' . $block->getCronError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,38 +75,52 @@ if (empty($aAllBlocks)) {
|
|||||||
$log->logDebug('No new blocks without share_id found in database');
|
$log->logDebug('No new blocks without share_id found in database');
|
||||||
} else {
|
} else {
|
||||||
// Loop through our unaccounted blocks
|
// Loop through our unaccounted blocks
|
||||||
$log->logInfo("Block ID\t\tHeight\tAmount\tShare ID\tShares\tFinder\tType");
|
$log->logInfo("Block ID\tHeight\t\tAmount\tShare ID\tShares\tFinder\tWorker\t\tType");
|
||||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||||
if (empty($aBlock['share_id'])) {
|
if (empty($aBlock['share_id'])) {
|
||||||
// Fetch this blocks upstream ID
|
|
||||||
$aBlockInfo = $bitcoin->query('getblock', $aBlock['blockhash']);
|
|
||||||
if ($share->setUpstream($aBlockInfo, $block->getLastUpstreamId())) {
|
|
||||||
$iCurrentUpstreamId = $share->getUpstreamId();
|
|
||||||
$iAccountId = $user->getUserId($share->getUpstreamFinder());
|
|
||||||
} else {
|
|
||||||
$log->logFatal('Unable to fetch blocks upstream share, aborted:' . $share->getError());
|
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to fetch blocks " . $aBlock['height'] . " upstream share: " . $share->getError());
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch share information
|
// Fetch share information
|
||||||
if (!$iPreviousShareId = $block->getLastShareId()) {
|
if ( !$iPreviousShareId = $block->getLastShareId())
|
||||||
$iPreviousShareId = 0;
|
$iPreviousShareId = 0;
|
||||||
$log->logInfo('Unable to find highest share ID found so far, if this is your first block, this is normal.');
|
// Fetch this blocks upstream ID
|
||||||
}
|
$aBlockRPCInfo = $bitcoin->query('getblock', $aBlock['blockhash']);
|
||||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
|
if ($share->findUpstreamShare($aBlockRPCInfo, $iPreviousShareId)) {
|
||||||
|
$iCurrentUpstreamId = $share->getUpstreamShareId();
|
||||||
// Store new information
|
// Rarely happens, but did happen once to me
|
||||||
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
|
if ($iCurrentUpstreamId == $iPreviousShareId) {
|
||||||
$log->logError('Failed to update share ID in database for block ' . $aBlock['height']);
|
$log->logFatal($share->getErrorMsg('E0063'));
|
||||||
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
$monitoring->endCronjob($cron_name, 'E0063', 1, true);
|
||||||
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height']);
|
}
|
||||||
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
// Out of order share detection
|
||||||
$log->logError('Failed to update share count in database for block ' . $aBlock['height']);
|
if ($iCurrentUpstreamId < $iPreviousShareId) {
|
||||||
if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
|
// Fetch our offending block
|
||||||
$log->logError('Failed to create Bonus transaction in database for user ' . $user->getUserName($iAccountId) . ' for block ' . $aBlock['height']);
|
$aBlockError = $block->getBlockByShareId($iPreviousShareId);
|
||||||
|
$log->logError('E0001: The block with height ' . $aBlock['height'] . ' found share ' . $iCurrentUpstreamId . ' which is < than ' . $iPreviousShareId . ' of block ' . $aBlockError['height'] . '.');
|
||||||
|
if ( !$aShareError = $share->getShareById($aBlockError['share_id']) || !$aShareCurrent = $share->getShareById($iCurrentUpstreamId)) {
|
||||||
|
// We were not able to fetch all shares that were causing this detection to trigger, bail out
|
||||||
|
$log->logFatal('E0002: Failed to fetch both offending shares ' . $iCurrentUpstreamId . ' and ' . $iPreviousShareId . '. Block height: ' . $aBlock['height']);
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0002', 1, true);
|
||||||
|
}
|
||||||
|
// Shares seem to be out of order, so lets change them
|
||||||
|
if ( !$share->updateShareById($iCurrentUpstreamId, $aShareError) || !$share->updateShareById($iPreviousShareId, $aShareCurrent)) {
|
||||||
|
// We couldn't update one of the shares! That might mean they have been deleted already
|
||||||
|
$log->logFatal('E0003: Failed to change shares order: ' . $share->getCronError());
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0003', 1, true);
|
||||||
|
}
|
||||||
|
// Reset our offending block so the next run re-checks the shares
|
||||||
|
if (!$block->setShareId($aBlockError['id'], NULL) && !$block->setFinder($aBlockError['id'], NULL) || !$block->setShares($aBlockError['id'], NULL)) {
|
||||||
|
$log->logFatal('E0004: Failed to reset previous block: ' . $aBlockError['height']);
|
||||||
|
$log->logError('Failed to reset block in database: ' . $aBlockError['height']);
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0004', 1, true);
|
||||||
|
}
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0007', 0, true);
|
||||||
|
} else {
|
||||||
|
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
|
||||||
|
$iAccountId = $user->getUserId($share->getUpstreamFinder());
|
||||||
|
$iWorker = $share->getUpstreamWorker();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$log->logFatal('E0005: Unable to fetch blocks upstream share, aborted:' . $share->getCronError());
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0005', 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$log->logInfo(
|
$log->logInfo(
|
||||||
@ -119,9 +130,23 @@ if (empty($aAllBlocks)) {
|
|||||||
. $iCurrentUpstreamId . "\t\t"
|
. $iCurrentUpstreamId . "\t\t"
|
||||||
. $iRoundShares . "\t"
|
. $iRoundShares . "\t"
|
||||||
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t"
|
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t"
|
||||||
|
. $iWorker . "\t"
|
||||||
. $share->share_type
|
. $share->share_type
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Store new information
|
||||||
|
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
|
||||||
|
$log->logError('Failed to update share ID in database for block ' . $aBlock['height'] . ': ' . $block->getCronError());
|
||||||
|
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
||||||
|
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height'] . ': ' . $block->getCronError());
|
||||||
|
if (!$block->setFindingWorker($aBlock['id'], $iWorker))
|
||||||
|
$log->logError('Failed to update worker ID in database for block ' . $aBlock['height'] . ': ' . $block->getCronError());
|
||||||
|
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
||||||
|
$log->logError('Failed to update share count in database for block ' . $aBlock['height'] . ': ' . $block->getCronError());
|
||||||
|
if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
|
||||||
|
$log->logError('Failed to create Bonus transaction in database for user ' . $user->getUserName($iAccountId) . ' for block ' . $aBlock['height'] . ': ' . $transaction->getCronError());
|
||||||
|
}
|
||||||
|
|
||||||
if ($setting->getValue('disable_notifications') != 1) {
|
if ($setting->getValue('disable_notifications') != 1) {
|
||||||
// Notify users
|
// Notify users
|
||||||
$aAccounts = $notification->getNotificationAccountIdByType('new_block');
|
$aAccounts = $notification->getNotificationAccountIdByType('new_block');
|
||||||
|
|||||||
@ -26,20 +26,13 @@ chdir(dirname(__FILE__));
|
|||||||
require_once('shared.inc.php');
|
require_once('shared.inc.php');
|
||||||
|
|
||||||
if ($setting->getValue('disable_mp') == 1) {
|
if ($setting->getValue('disable_mp') == 1) {
|
||||||
$log->logInfo(" auto payout disabled via admin panel");
|
$log->logInfo(" manual payout disabled via admin panel");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0009', 0, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Auto-Payout disabled");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
$monitoring->setStatus($cron_name . "_endtime", "date", time());
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($bitcoin->can_connect() !== true) {
|
if ($bitcoin->can_connect() !== true) {
|
||||||
$log->logFatal(" unable to connect to RPC server, exiting");
|
$log->logFatal(" unable to connect to RPC server, exiting");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0006', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable to connect to RPC server");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch outstanding payout requests
|
// Fetch outstanding payout requests
|
||||||
@ -53,6 +46,12 @@ if (count($aPayouts) > 0) {
|
|||||||
$aData['coin_address'] = $user->getCoinAddress($aData['account_id']);
|
$aData['coin_address'] = $user->getCoinAddress($aData['account_id']);
|
||||||
$aData['username'] = $user->getUserName($aData['account_id']);
|
$aData['username'] = $user->getUserName($aData['account_id']);
|
||||||
if ($dBalance > $config['txfee']) {
|
if ($dBalance > $config['txfee']) {
|
||||||
|
// To ensure we don't run this transaction again, lets mark it completed
|
||||||
|
if (!$oPayout->setProcessed($aData['id'])) {
|
||||||
|
$log->logFatal('unable to mark transactions ' . $aData['id'] . ' as processed.');
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0010', 1, true);
|
||||||
|
}
|
||||||
|
|
||||||
$log->logInfo("\t" . $aData['account_id'] . "\t\t" . $aData['username'] . "\t" . $dBalance . "\t\t" . $aData['coin_address']);
|
$log->logInfo("\t" . $aData['account_id'] . "\t\t" . $aData['username'] . "\t" . $dBalance . "\t\t" . $aData['coin_address']);
|
||||||
try {
|
try {
|
||||||
$aStatus = $bitcoin->validateaddress($aData['coin_address']);
|
$aStatus = $bitcoin->validateaddress($aData['coin_address']);
|
||||||
@ -65,21 +64,13 @@ if (count($aPayouts) > 0) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee']);
|
$txid = $bitcoin->sendtoaddress($aData['coin_address'], $dBalance - $config['txfee']);
|
||||||
} catch (BitcoinClientException $e) {
|
} catch (BitcoinClientException $e) {
|
||||||
$log->logError('Failed to send requested balance to coin address, please check payout process');
|
$log->logError('Failed to send requested balance to coin address, please check payout process');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// To ensure we don't run this transaction again, lets mark it completed
|
|
||||||
if (!$oPayout->setProcessed($aData['id'])) {
|
|
||||||
$log->logFatal('unable to mark transactions ' . $aData['id'] . ' as processed.');
|
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Unable set payout as processed");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($transaction->addTransaction($aData['account_id'], $dBalance - $config['txfee'], 'Debit_MP', NULL, $aData['coin_address']) && $transaction->addTransaction($aData['account_id'], $config['txfee'], 'TXFee', NULL, $aData['coin_address'])) {
|
if ($transaction->addTransaction($aData['account_id'], $dBalance - $config['txfee'], 'Debit_MP', NULL, $aData['coin_address'], $txid) && $transaction->addTransaction($aData['account_id'], $config['txfee'], 'TXFee', NULL, $aData['coin_address'])) {
|
||||||
// Mark all older transactions as archived
|
// Mark all older transactions as archived
|
||||||
if (!$transaction->setArchived($aData['account_id'], $transaction->insert_id))
|
if (!$transaction->setArchived($aData['account_id'], $transaction->insert_id))
|
||||||
$log->logError('Failed to mark transactions for #' . $aData['account_id'] . ' prior to #' . $transaction->insert_id . ' as archived');
|
$log->logError('Failed to mark transactions for #' . $aData['account_id'] . ' prior to #' . $transaction->insert_id . ' as archived');
|
||||||
@ -91,7 +82,8 @@ if (count($aPayouts) > 0) {
|
|||||||
if (!$notification->sendNotification($aData['account_id'], 'manual_payout', $aMailData))
|
if (!$notification->sendNotification($aData['account_id'], 'manual_payout', $aMailData))
|
||||||
$log->logError('Failed to send notification email to users address: ' . $aMailData['email']);
|
$log->logError('Failed to send notification email to users address: ' . $aMailData['email']);
|
||||||
} else {
|
} else {
|
||||||
$log->logError('Failed to add new Debit_MP transaction in database for user ' . $user->getUserName($aData['account_id']));
|
$log->logFatal('Failed to add new Debit_MP transaction in database for user ' . $user->getUserName($aData['account_id']));
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0064', 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,10 +26,7 @@ chdir(dirname(__FILE__));
|
|||||||
require_once('shared.inc.php');
|
require_once('shared.inc.php');
|
||||||
|
|
||||||
if ($setting->getValue('disable_notifications') == 1) {
|
if ($setting->getValue('disable_notifications') == 1) {
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0009', 0, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Cron disabled by admin");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$log->logDebug(" IDLE Worker Notifications ...");
|
$log->logDebug(" IDLE Worker Notifications ...");
|
||||||
@ -45,9 +42,9 @@ if (empty($aWorkers)) {
|
|||||||
$aData['subject'] = 'IDLE Worker : ' . $aWorker['username'];
|
$aData['subject'] = 'IDLE Worker : ' . $aWorker['username'];
|
||||||
$aData['worker'] = $aWorker['username'];
|
$aData['worker'] = $aWorker['username'];
|
||||||
$aData['email'] = $user->getUserEmail($aData['username']);
|
$aData['email'] = $user->getUserEmail($aData['username']);
|
||||||
$log->logInfo(" " . $aWorker['username'] . "...");
|
$log->logDebug(" " . $aWorker['username'] . "...");
|
||||||
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData))
|
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData))
|
||||||
$log->logError(" Failed sending notifications: " . $notification->getError() . "\n");
|
$log->logDebug(" Failed sending notifications: " . $notification->getCronError() . "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,15 +57,15 @@ if (!empty($aNotifications)) {
|
|||||||
foreach ($aNotifications as $aNotification) {
|
foreach ($aNotifications as $aNotification) {
|
||||||
$aData = json_decode($aNotification['data'], true);
|
$aData = json_decode($aNotification['data'], true);
|
||||||
$aWorker = $worker->getWorker($aData['id']);
|
$aWorker = $worker->getWorker($aData['id']);
|
||||||
$log->logInfo(" " . $aWorker['username'] . " ...");
|
$log->logDebug(" " . $aWorker['username'] . " ...");
|
||||||
if ($aWorker['hashrate'] > 0) {
|
if ($aWorker['hashrate'] > 0) {
|
||||||
if ($notification->setInactive($aNotification['id'])) {
|
if ($notification->setInactive($aNotification['id'])) {
|
||||||
$log->logInfo(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
|
$log->logDebug(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
|
||||||
} else {
|
} else {
|
||||||
$log->logInfo(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
|
$log->logError(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$log->logInfo(" still inactive\n");
|
$log->logDebug(" still inactive\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -35,37 +35,50 @@ if ($config['payout_system'] != 'pplns') {
|
|||||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||||
if (empty($aAllBlocks)) {
|
if (empty($aAllBlocks)) {
|
||||||
$log->logDebug("No new unaccounted blocks found");
|
$log->logDebug("No new unaccounted blocks found");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0011', 0, true, false);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "No new unaccounted blocks");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||||
|
// If we have unaccounted blocks without share_ids, they might not have been inserted yet
|
||||||
|
if (!$aBlock['share_id']) {
|
||||||
|
$log->logError('E0062: Block has no share_id, not running payouts');
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0062', 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
// We support some dynamic share targets but fall back to our fixed value
|
// We support some dynamic share targets but fall back to our fixed value
|
||||||
// Re-calculate after each run due to re-targets in this loop
|
// Re-calculate after each run due to re-targets in this loop
|
||||||
if ($config['pplns']['shares']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
if ($config['pplns']['shares']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
||||||
$pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']));
|
$pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']));
|
||||||
|
} else if ($config['pplns']['shares']['type'] == 'dynamic' && $block->getBlockCount() > 0) {
|
||||||
|
$pplns_target = round($block->getAvgBlockShares($aBlock['height'], $config['pplns']['blockavg']['blockcount']) * (100 - $config['pplns']['dynamic']['percent'])/100 + $aBlock['shares'] * $config['pplns']['dynamic']['percent']/100);
|
||||||
} else {
|
} else {
|
||||||
$pplns_target = $config['pplns']['shares']['default'];
|
$pplns_target = $config['pplns']['shares']['default'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$aBlock['accounted'] && $aBlock['height'] > $setting->getValue('last_accounted_block_height')) {
|
// Fetch our last paid block information
|
||||||
|
if ($iLastBlockId = $setting->getValue('last_accounted_block_id')) {
|
||||||
|
$aLastAccountedBlock = $block->getBlockById($iLastBlockId);
|
||||||
|
} else {
|
||||||
|
// A fake block to ensure payouts get started on first round
|
||||||
|
$iLastBlockId = 0;
|
||||||
|
$aLastAccountedBlock = array('height' => 0, 'confirmations' => 1);
|
||||||
|
}
|
||||||
|
// Ensure we are not paying out twice, ignore if the previous paid block is orphaned (-1 confirmations) and payout anyway
|
||||||
|
if ((!$aBlock['accounted'] && $aBlock['height'] > $aLastAccountedBlock['height']) || (@$aLastAccountedBlock['confirmations'] == -1)) {
|
||||||
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
||||||
$iCurrentUpstreamId = $aBlock['share_id'];
|
$iCurrentUpstreamId = $aBlock['share_id'];
|
||||||
if (!is_numeric($iCurrentUpstreamId)) {
|
if (!is_numeric($iCurrentUpstreamId)) {
|
||||||
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue");
|
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue");
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0012', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Block " . $aBlock['height'] . " has no share_id associated with it");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']);
|
$iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']);
|
||||||
$iNewRoundShares = 0;
|
$iNewRoundShares = 0;
|
||||||
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
|
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
|
||||||
$aRoundAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
|
$aRoundAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
|
||||||
|
|
||||||
|
$log->logInfo('Target: ' . $pplns_target . '; Shares: ' . $iRoundShares . '; Height: ' . $aBlock['height'] . '; Amount: ' . $aBlock['amount'] . '; Found by ID: ' . $aBlock['account_id']);
|
||||||
|
|
||||||
if ($iRoundShares >= $pplns_target) {
|
if ($iRoundShares >= $pplns_target) {
|
||||||
$log->logDebug("Matching or exceeding PPLNS target of $pplns_target with $iRoundShares");
|
$log->logDebug("Matching or exceeding PPLNS target of $pplns_target with $iRoundShares");
|
||||||
$iMinimumShareId = $share->getMinimumShareId($pplns_target, $aBlock['share_id']);
|
$iMinimumShareId = $share->getMinimumShareId($pplns_target, $aBlock['share_id']);
|
||||||
@ -73,15 +86,12 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
$aAccountShares = $share->getSharesForAccounts($iMinimumShareId - 1, $aBlock['share_id']);
|
$aAccountShares = $share->getSharesForAccounts($iMinimumShareId - 1, $aBlock['share_id']);
|
||||||
if (empty($aAccountShares)) {
|
if (empty($aAccountShares)) {
|
||||||
$log->logFatal("No shares found for this block, aborted! Block Height : " . $aBlock['height']);
|
$log->logFatal("No shares found for this block, aborted! Block Height : " . $aBlock['height']);
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0013', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block: " . $aBlock['height']);
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
foreach($aAccountShares as $key => $aData) {
|
foreach($aAccountShares as $key => $aData) {
|
||||||
$iNewRoundShares += $aData['valid'];
|
$iNewRoundShares += $aData['valid'];
|
||||||
}
|
}
|
||||||
$log->logInfo('Adjusting round target to PPLNS target ' . $iNewRoundShares);
|
$log->logInfo('Adjusting round to PPLNS target of ' . $pplns_target . ' shares used ' . $iNewRoundShares);
|
||||||
$iRoundShares = $iNewRoundShares;
|
$iRoundShares = $iNewRoundShares;
|
||||||
} else {
|
} else {
|
||||||
$log->logDebug("Not able to match PPLNS target of $pplns_target with $iRoundShares");
|
$log->logDebug("Not able to match PPLNS target of $pplns_target with $iRoundShares");
|
||||||
@ -90,10 +100,7 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
$aAccountShares = $aRoundAccountShares;
|
$aAccountShares = $aRoundAccountShares;
|
||||||
if (empty($aAccountShares)) {
|
if (empty($aAccountShares)) {
|
||||||
$log->logFatal("No shares found for this block, aborted! Block height: " . $aBlock['height']);
|
$log->logFatal("No shares found for this block, aborted! Block height: " . $aBlock['height']);
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0013', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block: " . $aBlock['height']);
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab only the most recent shares from Archive that fill the missing shares
|
// Grab only the most recent shares from Archive that fill the missing shares
|
||||||
@ -114,6 +121,24 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
$aAccountShares[$key]['invalid'] += $aArchiveShares[$aData['username']]['invalid'];
|
$aAccountShares[$key]['invalid'] += $aArchiveShares[$aData['username']]['invalid'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// reverse payout
|
||||||
|
if ($config['pplns']['reverse_payout']) {
|
||||||
|
$aSharesData = NULL;
|
||||||
|
foreach($aAccountShares as $key => $aData) {
|
||||||
|
$aSharesData[$aData['username']] = $aData;
|
||||||
|
}
|
||||||
|
// Add users from archive not in current round
|
||||||
|
foreach($aArchiveShares as $key => $aArchData) {
|
||||||
|
if (!array_key_exists($aArchData['account'], $aSharesData)) {
|
||||||
|
$log->logDebug('Adding user ' . $aArchData['account'] . ' to round shares');
|
||||||
|
$log->logDebug(' valid : ' . $aArchData['valid']);
|
||||||
|
$log->logDebug(' invalid : ' . $aArchData['invalid']);
|
||||||
|
$aArchData['username'] = $aArchData['account'];
|
||||||
|
$aSharesData[$aArchData['account']] = $aArchData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$aAccountShares = $aSharesData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// We tried to fill up to PPLNS target, now we need to check the actual shares to properly payout users
|
// We tried to fill up to PPLNS target, now we need to check the actual shares to properly payout users
|
||||||
foreach($aAccountShares as $key => $aData) {
|
foreach($aAccountShares as $key => $aData) {
|
||||||
@ -159,44 +184,55 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
foreach ($aRoundAccountShares as $key => $aRoundData) {
|
foreach ($aRoundAccountShares as $key => $aRoundData) {
|
||||||
if ($aRoundData['username'] == $aData['username'])
|
if ($aRoundData['username'] == $aData['username'])
|
||||||
if (!$statistics->updateShareStatistics($aRoundData, $aBlock['id']))
|
if (!$statistics->updateShareStatistics($aRoundData, $aBlock['id']))
|
||||||
$log->logError('Failed to update share statistics for ' . $aData['username']);
|
$log->logError('Failed to update share statistics for ' . $aData['username'] . ': ' . $statistics->getCronError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add PPLNS share statistics
|
||||||
|
foreach ($aAccountShares as $key => $aRoundData) {
|
||||||
|
if ($aRoundData['username'] == $aData['username']){
|
||||||
|
if (@$statistics->getIdShareStatistics($aRoundData, $aBlock['id'])){
|
||||||
|
if (!$statistics->updatePPLNSShareStatistics($aRoundData, $aBlock['id']))
|
||||||
|
$log->logError('Failed to update pplns statistics for ' . $aData['username'] . ': ' . $statistics->getCronError());
|
||||||
|
} else {
|
||||||
|
if (!$statistics->insertPPLNSShareStatistics($aRoundData, $aBlock['id']))
|
||||||
|
$log->logError('Failed to insert pplns statistics for ' . $aData['username'] . ': ' . $statistics->getCronError());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new credit transaction
|
// Add new credit transaction
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
// Add new fee debit for this block
|
// Add new fee debit for this block
|
||||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
// Add new donation debit
|
// Add new donation debit
|
||||||
if ($aData['donation'] > 0)
|
if ($aData['donation'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store this blocks height as last accounted for
|
// Store this blocks height as last accounted for
|
||||||
$setting->setValue('last_accounted_block_height', $aBlock['height']);
|
$setting->setValue('last_accounted_block_id', $aBlock['id']);
|
||||||
|
|
||||||
// Move counted shares to archive before this blockhash upstream share
|
// Move counted shares to archive before this blockhash upstream share
|
||||||
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
||||||
$log->logError('Failed to copy shares to archive table');
|
$log->logError('Failed to copy shares to archive table: ' . $share->getCronError() . ': ' . $share->getCronError());
|
||||||
// Delete all accounted shares
|
// Delete all accounted shares
|
||||||
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
||||||
$log->logFatal("Failed to delete accounted shares from $iPreviousShareId to $iCurrentUpstreamId, aborting!");
|
$log->logFatal("Failed to delete accounted shares from $iPreviousShareId to $iCurrentUpstreamId, aborting! Error: " . $share->getCronError());
|
||||||
exit(1);
|
$monitoring->endCronjob($cron_name, 'E0016', 1, true);
|
||||||
}
|
}
|
||||||
// Mark this block as accounted for
|
// Mark this block as accounted for
|
||||||
if (!$block->setAccounted($aBlock['id'])) {
|
if (!$block->setAccounted($aBlock['id'])) {
|
||||||
$log->logFatal("Failed to mark block as accounted! Aborting!");
|
$log->logFatal("Failed to mark block as accounted! Aborting! Error: " . $block->getCronError());
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0014', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$log->logFatal('Potential double payout detected. Aborted.');
|
||||||
$aMailData = array(
|
$aMailData = array(
|
||||||
'email' => $setting->getValue('website_email'),
|
'email' => $setting->getValue('system_error_email'),
|
||||||
'subject' => 'Payout processing aborted',
|
'subject' => 'Payout processing aborted',
|
||||||
'Error' => 'Potential double payout detected. All payouts halted until fixed!',
|
'Error' => 'Potential double payout detected. All payouts halted until fixed!',
|
||||||
'BlockID' => $aBlock['id'],
|
'BlockID' => $aBlock['id'],
|
||||||
@ -204,12 +240,8 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
'Block Share ID' => $aBlock['share_id']
|
'Block Share ID' => $aBlock['share_id']
|
||||||
);
|
);
|
||||||
if (!$mail->sendMail('notifications/error', $aMailData))
|
if (!$mail->sendMail('notifications/error', $aMailData))
|
||||||
$log->logError(" Failed sending notifications: " . $notification->getError() . "\n");
|
$log->logError(" Failed sending notifications: " . $notification->getCronError() . "\n");
|
||||||
$log->logFatal('Potential double payout detected. Aborted.');
|
$monitoring->endCronjob($cron_name, 'E0015', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Block height for block too low! Potential double payout detected.");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,19 +54,17 @@ if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() >
|
|||||||
if ($config['pps']['reward']['type'] == 'block') {
|
if ($config['pps']['reward']['type'] == 'block') {
|
||||||
if ($aLastBlock = $block->getLast()) {
|
if ($aLastBlock = $block->getLast()) {
|
||||||
$pps_reward = $aLastBlock['amount'];
|
$pps_reward = $aLastBlock['amount'];
|
||||||
$log->logInfo("PPS reward using last block, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
|
|
||||||
} else {
|
} else {
|
||||||
$pps_reward = $config['pps']['reward']['default'];
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
$log->logInfo("PPS reward using default, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$pps_reward = $config['pps']['reward']['default'];
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
$log->logInfo("PPS reward fixed default, amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Per-share value to be paid out to users
|
// Per-share value to be paid out to users
|
||||||
$pps_value = round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12);
|
$pps_value = round($pps_reward / (pow(2, $config['target_bits']) * $dDifficulty), 12);
|
||||||
|
|
||||||
|
|
||||||
// Find our last share accounted and last inserted share for PPS calculations
|
// Find our last share accounted and last inserted share for PPS calculations
|
||||||
$iPreviousShareId = $setting->getValue('pps_last_share_id');
|
$iPreviousShareId = $setting->getValue('pps_last_share_id');
|
||||||
@ -75,11 +73,16 @@ $iLastShareId = $share->getLastInsertedShareId();
|
|||||||
// Check for all new shares, we start one higher as our last accounted share to avoid duplicates
|
// Check for all new shares, we start one higher as our last accounted share to avoid duplicates
|
||||||
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId);
|
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId);
|
||||||
|
|
||||||
$log->logInfo("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee");
|
if (!empty($aAccountShares)) {
|
||||||
|
// Info for this payout
|
||||||
|
$log->logInfo("PPS reward type: " . $config['pps']['reward']['type'] . ", amount: " . $pps_reward . "\tdifficulty: " . $dDifficulty . "\tPPS value: " . $pps_value);
|
||||||
|
$log->logInfo("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee");
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($aAccountShares as $aData) {
|
foreach ($aAccountShares as $aData) {
|
||||||
// Take our valid shares and multiply by per share value
|
// MPOS uses a base difficulty setting to avoid showing weightened shares
|
||||||
$aData['payout'] = round($aData['valid'] * $pps_value, 8);
|
// Since we need weightened shares here, we go back to the proper value for payouts
|
||||||
|
$aData['payout'] = round($aData['valid'] * pow(2, ($config['difficulty'] - 16)) * $pps_value, 8);
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
$aData['fee' ] = 0;
|
$aData['fee' ] = 0;
|
||||||
@ -94,7 +97,7 @@ foreach ($aAccountShares as $aData) {
|
|||||||
$log->logInfo($aData['id'] . "\t" .
|
$log->logInfo($aData['id'] . "\t" .
|
||||||
$aData['username'] . "\t" .
|
$aData['username'] . "\t" .
|
||||||
$aData['invalid'] . "\t" .
|
$aData['invalid'] . "\t" .
|
||||||
$aData['valid'] . "\t*\t" .
|
$aData['valid'] * pow(2, ($config['difficulty'] - 16)) . "\t*\t" .
|
||||||
number_format($pps_value, 12) . "\t=\t" .
|
number_format($pps_value, 12) . "\t=\t" .
|
||||||
number_format($aData['payout'], 8) . "\t" .
|
number_format($aData['payout'], 8) . "\t" .
|
||||||
number_format($aData['donation'], 8) . "\t" .
|
number_format($aData['donation'], 8) . "\t" .
|
||||||
@ -102,15 +105,15 @@ foreach ($aAccountShares as $aData) {
|
|||||||
|
|
||||||
// Add new credit transaction
|
// Add new credit transaction
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
|
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
|
||||||
$log->logError('Failed to add Credit_PPS transaction in database');
|
$log->logError('Failed to add Credit_PPS transaction in database: ' . $transaction->getCronError());
|
||||||
// Add new fee debit for this block
|
// Add new fee debit for this block
|
||||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS'))
|
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS'))
|
||||||
$log->logError('Failed to add Fee_PPS transaction in database');
|
$log->logError('Failed to add Fee_PPS transaction in database: ' . $transaction->getCronError());
|
||||||
// Add new donation debit
|
// Add new donation debit
|
||||||
if ($aData['donation'] > 0)
|
if ($aData['donation'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS'))
|
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS'))
|
||||||
$log->logError('Failed to add Donation_PPS transaction in database');
|
$log->logError('Failed to add Donation_PPS transaction in database: ' . $transaction->getCronError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store our last inserted ID for the next run
|
// Store our last inserted ID for the next run
|
||||||
@ -118,7 +121,10 @@ $setting->setValue('pps_last_share_id', $iLastShareId);
|
|||||||
|
|
||||||
// Fetch all unaccounted blocks
|
// Fetch all unaccounted blocks
|
||||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||||
if (empty($aAllBlocks)) $log->logDebug("No new unaccounted blocks found");
|
if (empty($aAllBlocks)) {
|
||||||
|
$log->logDebug("No new unaccounted blocks found");
|
||||||
|
// No monitoring event here, not fatal for PPS
|
||||||
|
}
|
||||||
|
|
||||||
// Go through blocks and archive/delete shares that have been accounted for
|
// Go through blocks and archive/delete shares that have been accounted for
|
||||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||||
@ -135,28 +141,22 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
$aAccountShares = $share->getSharesForAccounts(@$iLastBlockShare, $aBlock['share_id']);
|
$aAccountShares = $share->getSharesForAccounts(@$iLastBlockShare, $aBlock['share_id']);
|
||||||
foreach ($aAccountShares as $key => $aData) {
|
foreach ($aAccountShares as $key => $aData) {
|
||||||
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
||||||
$log->logError("Failed to update stats for this block on : " . $aData['username']);
|
$log->logError("Failed to update stats for this block on : " . $aData['username'] . ': ' . $statistics->getCronError());
|
||||||
}
|
}
|
||||||
// Move shares to archive
|
// Move shares to archive
|
||||||
if ($aBlock['share_id'] < $iLastShareId) {
|
if ($aBlock['share_id'] < $iLastShareId) {
|
||||||
if (!$share->moveArchive($aBlock['share_id'], $aBlock['id'], @$iLastBlockShare))
|
if (!$share->moveArchive($aBlock['share_id'], $aBlock['id'], @$iLastBlockShare))
|
||||||
$log->logError("Archving failed");
|
$log->logError("Failed to copy shares to archive: " . $share->getCronError() . ': ' . $share->getCronError());
|
||||||
}
|
}
|
||||||
// Delete shares
|
// Delete shares
|
||||||
if ($aBlock['share_id'] < $iLastShareId && !$share->deleteAccountedShares($aBlock['share_id'], $iLastBlockShare)) {
|
if ($aBlock['share_id'] < $iLastShareId && !$share->deleteAccountedShares($aBlock['share_id'], $iLastBlockShare)) {
|
||||||
$log->logFatal("Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!");
|
$log->logFatal("Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting! Error: " . $share->getCronError());
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0016', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare);
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
// Mark this block as accounted for
|
// Mark this block as accounted for
|
||||||
if (!$block->setAccounted($aBlock['id'])) {
|
if (!$block->setAccounted($aBlock['id'])) {
|
||||||
$log->logFatal("Failed to mark block as accounted! Aborting!");
|
$log->logFatal("Failed to mark block as accounted! Aborting! Error: " . $block->getCronError());
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0014', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -35,17 +35,30 @@ if ($config['payout_system'] != 'prop') {
|
|||||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||||
if (empty($aAllBlocks)) {
|
if (empty($aAllBlocks)) {
|
||||||
$log->logDebug('No new unaccounted blocks found in database');
|
$log->logDebug('No new unaccounted blocks found in database');
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0011', 0, true, false);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "No new unaccounted blocks");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 0);
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
// Table header for account shares
|
// Table header for account shares
|
||||||
$log->logInfo("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee");
|
$log->logInfo("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee");
|
||||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||||
if (!$aBlock['accounted'] && $aBlock['height'] > $setting->getValue('last_accounted_block_height')) {
|
// If we have unaccounted blocks without share_ids, they might not have been inserted yet
|
||||||
|
if (!$aBlock['share_id']) {
|
||||||
|
$log->logError('E0062: Block has no share_id, not running payouts');
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0062', 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch last paid block information
|
||||||
|
if ($iLastBlockId = $setting->getValue('last_accounted_block_id')) {
|
||||||
|
$aLastAccountedBlock = $block->getBlockById($iLastBlockId);
|
||||||
|
} else {
|
||||||
|
// A fake block to ensure payouts get started on first round
|
||||||
|
$iLastBlockId = 0;
|
||||||
|
$aLastAccountedBlock = array('height' => 0, 'confirmations' => 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we are not paying out twice, ignore if the previous paid block is orphaned (-1 confirmations) and payout anyway
|
||||||
|
if ((!$aBlock['accounted'] && $aBlock['height'] > $aLastAccountedBlock['height']) || (@$aLastAccountedBlock['confirmations'] == -1)) {
|
||||||
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
|
||||||
$iCurrentUpstreamId = $aBlock['share_id'];
|
$iCurrentUpstreamId = $aBlock['share_id'];
|
||||||
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
|
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
|
||||||
@ -54,10 +67,7 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
|
|
||||||
if (empty($aAccountShares)) {
|
if (empty($aAccountShares)) {
|
||||||
$log->logFatal('No shares found for this block, aborted: ' . $aBlock['height']);
|
$log->logFatal('No shares found for this block, aborted: ' . $aBlock['height']);
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0013', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "No shares found for this block, aborted: " . $aBlock['height']);
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all accounts that have found shares for this round
|
// Loop through all accounts that have found shares for this round
|
||||||
@ -86,46 +96,40 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
|
|
||||||
// Update user share statistics
|
// Update user share statistics
|
||||||
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
|
||||||
$log->logFatal('Failed to update share statistics for ' . $aData['username']);
|
$log->logFatal('Failed to update share statistics for ' . $aData['username'] . ': ' . $statistics->getCronError());
|
||||||
// Add new credit transaction
|
// Add new credit transaction
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
// Add new fee debit for this block
|
// Add new fee debit for this block
|
||||||
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
if ($aData['fee'] > 0 && $config['fees'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
// Add new donation debit
|
// Add new donation debit
|
||||||
if ($aData['donation'] > 0)
|
if ($aData['donation'] > 0)
|
||||||
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
|
||||||
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username']);
|
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username'] . ': ' . $transaction->getCronError());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add block as accounted for into settings table
|
// Add block as accounted for into settings table
|
||||||
$setting->setValue('last_accounted_block_height', $aBlock['height']);
|
$setting->setValue('last_accounted_block_id', $aBlock['id']);
|
||||||
|
|
||||||
// Move counted shares to archive before this blockhash upstream share
|
// Move counted shares to archive before this blockhash upstream share
|
||||||
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
if (!$share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId))
|
||||||
$log->logError('Failed to copy shares to archive');
|
$log->logError('Failed to copy shares to archive: ' . $share->getCronError());
|
||||||
// Delete all accounted shares
|
// Delete all accounted shares
|
||||||
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
|
||||||
$log->logFatal('Failed to delete accounted shares from ' . $iPreviousShareId . ' to ' . $iCurrentUpstreamId . ', aborted');
|
$log->logFatal('Failed to delete accounted shares from ' . $iPreviousShareId . ' to ' . $iCurrentUpstreamId . ', aborted! Error: ' . $share->getCronError());
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0016', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to delete accounted shares from " . $iPreviousShareId . " to " . $iCurrentUpstreamId);
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
// Mark this block as accounted for
|
// Mark this block as accounted for
|
||||||
if (!$block->setAccounted($aBlock['id'])) {
|
if (!$block->setAccounted($aBlock['id'])) {
|
||||||
$log->logFatal('Failed to mark block as accounted! Aborted.');
|
$log->logFatal('Failed to mark block as accounted! Aborted! Error: ' . $block->getCronError());
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0014', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", "Failed to mark block " . $aBlock['height'] . " as accounted");
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$log->logFatal('Possible double payout detected. Aborted.');
|
$log->logFatal('Potential double payout detected. Aborted.');
|
||||||
$aMailData = array(
|
$aMailData = array(
|
||||||
'email' => $setting->getValue('website_email'),
|
'email' => $setting->getValue('system_error_email'),
|
||||||
'subject' => 'Payout Failure: Double Payout',
|
'subject' => 'Payout Failure: Double Payout',
|
||||||
'Error' => 'Possible double payout detected',
|
'Error' => 'Possible double payout detected',
|
||||||
'BlockID' => $aBlock['id'],
|
'BlockID' => $aBlock['id'],
|
||||||
@ -133,11 +137,8 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
|
|||||||
'Block Share ID' => $aBlock['share_id']
|
'Block Share ID' => $aBlock['share_id']
|
||||||
);
|
);
|
||||||
if (!$mail->sendMail('notifications/error', $aMailData))
|
if (!$mail->sendMail('notifications/error', $aMailData))
|
||||||
$log->logError(" Failed sending notifications: " . $notification->getError() . "\n");
|
$log->logFatal('Potential double payout detected. Aborted.');
|
||||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
$monitoring->endCronjob($cron_name, 'E0015', 1, true);
|
||||||
$monitoring->setStatus($cron_name . "_message", "message", 'Possible double payout detected. Aborted.');
|
|
||||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,17 +29,32 @@ SUBFOLDER=""
|
|||||||
# #
|
# #
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
|
# Mac OS detection
|
||||||
|
OS=`uname`
|
||||||
|
|
||||||
|
|
||||||
|
case "$OS" in
|
||||||
|
Darwin) READLINK=$( which greadlink ) ;;
|
||||||
|
*) READLINK=$( which readlink ) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ ! -x $READLINK ]]; then
|
||||||
|
echo "readlink not found, please install first";
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
# My own name
|
# My own name
|
||||||
ME=$( basename $0 )
|
ME=$( basename $0 )
|
||||||
|
|
||||||
# Overwrite some settings via command line arguments
|
# Overwrite some settings via command line arguments
|
||||||
while getopts "hvp:d:" opt; do
|
while getopts "hfvp:d:" opt; do
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
h|\?)
|
h|\?)
|
||||||
echo "Usage: $0 [-v] [-p PHP_BINARY] [-d SUBFOLDER]";
|
echo "Usage: $0 [-v] [-p PHP_BINARY] [-d SUBFOLDER]";
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
v) VERBOSE=1 ;;
|
v) VERBOSE=1 ;;
|
||||||
|
f) PHP_OPTS="$PHP_OPTS -f";;
|
||||||
p) PHP_BIN=$OPTARG ;;
|
p) PHP_BIN=$OPTARG ;;
|
||||||
d) SUBFOLDER=$OPTARG ;;
|
d) SUBFOLDER=$OPTARG ;;
|
||||||
:)
|
:)
|
||||||
@ -52,7 +67,7 @@ done
|
|||||||
# Path to PID file, needs to be writable by user running this
|
# Path to PID file, needs to be writable by user running this
|
||||||
PIDFILE="${BASEPATH}/${SUBFOLDER}/${ME}.pid"
|
PIDFILE="${BASEPATH}/${SUBFOLDER}/${ME}.pid"
|
||||||
# Clean PIDFILE path
|
# Clean PIDFILE path
|
||||||
PIDFILE=$(readlink -m "$PIDFILE")
|
PIDFILE=$($READLINK -m "$PIDFILE")
|
||||||
|
|
||||||
# Create folders recursively if necessary
|
# Create folders recursively if necessary
|
||||||
if ! $(mkdir -p $( dirname $PIDFILE)); then
|
if ! $(mkdir -p $( dirname $PIDFILE)); then
|
||||||
@ -62,7 +77,7 @@ fi
|
|||||||
|
|
||||||
# Find scripts path
|
# Find scripts path
|
||||||
if [[ -L $0 ]]; then
|
if [[ -L $0 ]]; then
|
||||||
CRONHOME=$( dirname $( readlink $0 ) )
|
CRONHOME=$( dirname $( $READLINK $0 ) )
|
||||||
else
|
else
|
||||||
CRONHOME=$( dirname $0 )
|
CRONHOME=$( dirname $0 )
|
||||||
fi
|
fi
|
||||||
@ -104,7 +119,7 @@ echo $PID > $PIDFILE
|
|||||||
|
|
||||||
for cron in $CRONS; do
|
for cron in $CRONS; do
|
||||||
[[ $VERBOSE == 1 ]] && echo "Running $cron, check logfile for details"
|
[[ $VERBOSE == 1 ]] && echo "Running $cron, check logfile for details"
|
||||||
$PHP_BIN $cron
|
$PHP_BIN $cron $PHP_OPTS
|
||||||
done
|
done
|
||||||
|
|
||||||
# Remove pidfile
|
# Remove pidfile
|
||||||
|
|||||||
@ -41,6 +41,16 @@ require_once(BASEPATH . 'include/config/global.inc.php');
|
|||||||
// We include all needed files here, even though our templates could load them themself
|
// We include all needed files here, even though our templates could load them themself
|
||||||
require_once(INCLUDE_DIR . '/autoloader.inc.php');
|
require_once(INCLUDE_DIR . '/autoloader.inc.php');
|
||||||
|
|
||||||
|
// Command line switches
|
||||||
|
array_shift($argv);
|
||||||
|
foreach ($argv as $option) {
|
||||||
|
switch ($option) {
|
||||||
|
case '-f':
|
||||||
|
$monitoring->setStatus($cron_name . "_disabled", "yesno", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load 3rd party logging library for running crons
|
// Load 3rd party logging library for running crons
|
||||||
$log = new KLogger ( 'logs/' . $cron_name . '.txt' , KLogger::INFO );
|
$log = new KLogger ( 'logs/' . $cron_name . '.txt' , KLogger::INFO );
|
||||||
$log->LogDebug('Starting ' . $cron_name);
|
$log->LogDebug('Starting ' . $cron_name);
|
||||||
@ -48,8 +58,13 @@ $log->LogDebug('Starting ' . $cron_name);
|
|||||||
// Load the start time for later runtime calculations for monitoring
|
// Load the start time for later runtime calculations for monitoring
|
||||||
$cron_start[$cron_name] = microtime(true);
|
$cron_start[$cron_name] = microtime(true);
|
||||||
|
|
||||||
|
// Check if our cron is activated
|
||||||
|
if ($monitoring->isDisabled($cron_name)) {
|
||||||
|
$log->logFatal('Cronjob is currently disabled due to errors, use -f option to force running cron.');
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0018', 1, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark cron as running for monitoring
|
// Mark cron as running for monitoring
|
||||||
$log->logDebug('Marking cronjob as running for monitoring');
|
$log->logDebug('Marking cronjob as running for monitoring');
|
||||||
$monitoring->setStatus($cron_name . '_active', 'yesno', 1);
|
|
||||||
$monitoring->setStatus($cron_name . '_starttime', 'date', time());
|
$monitoring->setStatus($cron_name . '_starttime', 'date', time());
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -28,12 +28,26 @@ require_once('shared.inc.php');
|
|||||||
// Include additional file not set in autoloader
|
// Include additional file not set in autoloader
|
||||||
require_once(CLASS_DIR . '/tools.class.php');
|
require_once(CLASS_DIR . '/tools.class.php');
|
||||||
|
|
||||||
|
// Fetch latest coin price via API call
|
||||||
if ($price = $tools->getPrice()) {
|
if ($price = $tools->getPrice()) {
|
||||||
$log->logInfo("Price update: found $price as price");
|
$log->logDebug("Price update: found $price as price");
|
||||||
if (!$setting->setValue('price', $price))
|
if (!$setting->setValue('price', $price))
|
||||||
$log->logError("unable to update value in settings table");
|
$log->logError("unable to update value in settings table");
|
||||||
} else {
|
} else {
|
||||||
$log->logFatal("failed to fetch API data: " . $tools->getError());
|
$log->logError("failed to fetch API data: " . $tools->getCronError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update Uptime Robot status in Settings table via API call
|
||||||
|
if ($api_keys = $setting->getValue('monitoring_uptimerobot_api_keys')) {
|
||||||
|
if (!strstr($api_keys, '<API KEY>|<MONITOR ID>')) {
|
||||||
|
$monitoring->setTools($tools);
|
||||||
|
if (!$monitoring->storeUptimeRobotStatus()) {
|
||||||
|
$log->logError($monitoring->getCronError());
|
||||||
|
$monitoring->endCronjob($cron_name, 'E0017', 1, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$log->logDebug('Skipped Uptime Robot API update, missing api keys');
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once('cron_end.inc.php');
|
require_once('cron_end.inc.php');
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
ErrorDocument 404 /index.php?page=error&action=404
|
||||||
RedirectMatch 404 /templates(/|$)
|
RedirectMatch 404 /templates(/|$)
|
||||||
RedirectMatch 404 /include(/|$)
|
RedirectMatch 404 /include(/|$)
|
||||||
RedirectMatch 404 /.git(/|$)
|
RedirectMatch 404 /.git(/|$)
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
// SHA/Scrypt check
|
||||||
|
|
||||||
|
if (empty($config['algorithm']) || $config['algorithm'] == 'scrypt') {
|
||||||
|
$config['target_bits'] = 16;
|
||||||
|
} else {
|
||||||
|
$config['target_bits'] = 32;
|
||||||
|
}
|
||||||
// Default classes
|
// Default classes
|
||||||
require_once(CLASS_DIR . '/debug.class.php');
|
require_once(CLASS_DIR . '/debug.class.php');
|
||||||
require_once(INCLUDE_DIR . '/lib/KLogger.php');
|
require_once(INCLUDE_DIR . '/lib/KLogger.php');
|
||||||
require_once(INCLUDE_DIR . '/database.inc.php');
|
require_once(INCLUDE_DIR . '/database.inc.php');
|
||||||
require_once(INCLUDE_DIR . '/config/memcache_keys.inc.php');
|
require_once(INCLUDE_DIR . '/config/memcache_keys.inc.php');
|
||||||
|
require_once(INCLUDE_DIR . '/config/error_codes.inc.php');
|
||||||
|
|
||||||
// We need to load these two first
|
// We need to load these two first
|
||||||
require_once(CLASS_DIR . '/base.class.php');
|
require_once(CLASS_DIR . '/base.class.php');
|
||||||
@ -44,8 +51,8 @@ require_once(CLASS_DIR . '/invitation.class.php');
|
|||||||
require_once(CLASS_DIR . '/share.class.php');
|
require_once(CLASS_DIR . '/share.class.php');
|
||||||
require_once(CLASS_DIR . '/worker.class.php');
|
require_once(CLASS_DIR . '/worker.class.php');
|
||||||
require_once(CLASS_DIR . '/statistics.class.php');
|
require_once(CLASS_DIR . '/statistics.class.php');
|
||||||
require_once(CLASS_DIR . '/roundstats.class.php');
|
|
||||||
require_once(CLASS_DIR . '/transaction.class.php');
|
require_once(CLASS_DIR . '/transaction.class.php');
|
||||||
|
require_once(CLASS_DIR . '/roundstats.class.php');
|
||||||
require_once(CLASS_DIR . '/notification.class.php');
|
require_once(CLASS_DIR . '/notification.class.php');
|
||||||
require_once(CLASS_DIR . '/news.class.php');
|
require_once(CLASS_DIR . '/news.class.php');
|
||||||
require_once(CLASS_DIR . '/api.class.php');
|
require_once(CLASS_DIR . '/api.class.php');
|
||||||
|
|||||||
@ -4,12 +4,21 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
// Our base class that defines
|
/**
|
||||||
// some cross-class functions.
|
* Our base class that we extend our other classes from
|
||||||
|
*
|
||||||
|
* It supplies some basic features as cross-linking with other classes
|
||||||
|
* after loading a newly created class.
|
||||||
|
**/
|
||||||
class Base {
|
class Base {
|
||||||
private $sError = '';
|
private $sError = '';
|
||||||
|
private $sCronError = '';
|
||||||
|
protected $table = '';
|
||||||
private $values = array(), $types = '';
|
private $values = array(), $types = '';
|
||||||
|
|
||||||
|
public function getTableName() {
|
||||||
|
return $this->table;
|
||||||
|
}
|
||||||
public function setDebug($debug) {
|
public function setDebug($debug) {
|
||||||
$this->debug = $debug;
|
$this->debug = $debug;
|
||||||
}
|
}
|
||||||
@ -19,6 +28,9 @@ class Base {
|
|||||||
public function setMail($mail) {
|
public function setMail($mail) {
|
||||||
$this->mail = $mail;
|
$this->mail = $mail;
|
||||||
}
|
}
|
||||||
|
public function setSalt($salt) {
|
||||||
|
$this->salt = $salt;
|
||||||
|
}
|
||||||
public function setSmarty($smarty) {
|
public function setSmarty($smarty) {
|
||||||
$this->smarty = $smarty;
|
$this->smarty = $smarty;
|
||||||
}
|
}
|
||||||
@ -28,39 +40,106 @@ class Base {
|
|||||||
public function setConfig($config) {
|
public function setConfig($config) {
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
}
|
}
|
||||||
|
public function setErrorCodes(&$aErrorCodes) {
|
||||||
|
$this->aErrorCodes =& $aErrorCodes;
|
||||||
|
}
|
||||||
public function setToken($token) {
|
public function setToken($token) {
|
||||||
$this->token = $token;
|
$this->token = $token;
|
||||||
}
|
}
|
||||||
public function setBlock($block) {
|
public function setBlock($block) {
|
||||||
$this->block = $block;
|
$this->block = $block;
|
||||||
}
|
}
|
||||||
|
public function setTransaction($transaction) {
|
||||||
|
$this->transaction = $transaction;
|
||||||
|
}
|
||||||
|
public function setMemcache($memcache) {
|
||||||
|
$this->memcache = $memcache;
|
||||||
|
}
|
||||||
|
public function setStatistics($statistics) {
|
||||||
|
$this->statistics = $statistics;
|
||||||
|
}
|
||||||
public function setSetting($setting) {
|
public function setSetting($setting) {
|
||||||
$this->setting = $setting;
|
$this->setting = $setting;
|
||||||
}
|
}
|
||||||
|
public function setTools($tools) {
|
||||||
|
$this->tools = $tools;
|
||||||
|
}
|
||||||
public function setBitcoin($bitcoin) {
|
public function setBitcoin($bitcoin) {
|
||||||
$this->bitcoin = $bitcoin;
|
$this->bitcoin = $bitcoin;
|
||||||
}
|
}
|
||||||
public function setTokenType($tokentype) {
|
public function setTokenType($tokentype) {
|
||||||
$this->tokentype = $tokentype;
|
$this->tokentype = $tokentype;
|
||||||
}
|
}
|
||||||
|
public function setShare($share) {
|
||||||
|
$this->share = $share;
|
||||||
|
}
|
||||||
public function setErrorMessage($msg) {
|
public function setErrorMessage($msg) {
|
||||||
$this->sError = $msg;
|
$this->sError = $msg;
|
||||||
|
// Default to same error for crons
|
||||||
|
$this->sCronError = $msg;
|
||||||
|
}
|
||||||
|
public function setCronMessage($msg) {
|
||||||
|
// Used to overwrite any errors with a custom cron one
|
||||||
|
$this->sCronError = $msg;
|
||||||
}
|
}
|
||||||
public function getError() {
|
public function getError() {
|
||||||
return $this->sError;
|
return $this->sError;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Additional information in error string for cronjobs logging
|
||||||
|
**/
|
||||||
|
public function getCronError() {
|
||||||
|
return $this->sCronError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get error message from error code array
|
||||||
|
* @param errCode string Error code string
|
||||||
|
* @param optional string Optional addtitional error strings to append
|
||||||
|
* @retrun string Error Message
|
||||||
|
**/
|
||||||
|
public function getErrorMsg($errCode='') {
|
||||||
|
if (!is_array($this->aErrorCodes)) return 'Error codes not loaded';
|
||||||
|
if (!array_key_exists($errCode, $this->aErrorCodes)) return 'Unknown Error Code: ' . $errCode;
|
||||||
|
if (func_num_args() > 1) {
|
||||||
|
$args = func_get_args();
|
||||||
|
array_shift($args);
|
||||||
|
$param_count = substr_count($this->aErrorCodes[$errCode], '%s');
|
||||||
|
if ($param_count == count($args)) {
|
||||||
|
return vsprintf($this->aErrorCodes[$errCode], $args);
|
||||||
|
} else {
|
||||||
|
return $this->aErrorCodes[$errCode] . ' (missing information to complete string)';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $this->aErrorCodes[$errCode];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an element as an associated array
|
||||||
|
**/
|
||||||
|
protected function getAllAssoc($value, $field='id', $type='i') {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE $field = ? LIMIT 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param($type, $value) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_assoc();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Get a single row from the table
|
* Get a single row from the table
|
||||||
* @param value string Value to search for
|
* @param value string Value to search for
|
||||||
* @param search Return column to search for
|
* @param search Return column to search for
|
||||||
* @param field string Search column
|
* @param field string Search column
|
||||||
* @param type string Type of value
|
* @param type string Type of value
|
||||||
|
* @param lower bool try with LOWER comparision
|
||||||
* @return array Return result
|
* @return array Return result
|
||||||
**/
|
**/
|
||||||
protected function getSingle($value, $search='id', $field='id', $type="i") {
|
protected function getSingle($value, $search='id', $field='id', $type="i", $lower=false) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("SELECT $search FROM $this->table WHERE $field = ? LIMIT 1");
|
$sql = "SELECT $search FROM $this->table WHERE";
|
||||||
|
$lower ? $sql .= " LOWER($field) = LOWER(?)" : $sql .= " $field = ?";
|
||||||
|
$sql .= " LIMIT 1";
|
||||||
|
$stmt = $this->mysqli->prepare($sql);
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt)) {
|
||||||
$stmt->bind_param($type, $value);
|
$stmt->bind_param($type, $value);
|
||||||
$stmt->execute();
|
$stmt->execute();
|
||||||
@ -72,18 +151,38 @@ class Base {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the prepared statement is valid
|
||||||
|
* @param $bState Statement return value
|
||||||
|
* @return bool true or false
|
||||||
|
**/
|
||||||
function checkStmt($bState) {
|
function checkStmt($bState) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if ($bState ===! true) {
|
if ($bState ===! true)
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Catch SQL errors with this method
|
||||||
|
* @param error_code string Error code to read
|
||||||
|
**/
|
||||||
|
protected function sqlError($error_code='E0020') {
|
||||||
|
// More human-readable error for UI
|
||||||
|
if (func_num_args() == 0) {
|
||||||
|
$this->setErrorMessage($this->getErrorMsg($error_code));
|
||||||
|
} else {
|
||||||
|
$this->setErrorMessage(call_user_func_array(array($this, 'getErrorMsg'), func_get_args()));
|
||||||
|
}
|
||||||
|
// Default to SQL error for debug and cron errors
|
||||||
|
$this->debug->append($this->getErrorMsg('E0019', $this->mysqli->error));
|
||||||
|
$this->setCronMessage($this->getErrorMsg('E0019', $this->mysqli->error));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a single row in a table
|
|
||||||
* @param userID int Account ID
|
* @param userID int Account ID
|
||||||
|
* Update a single row in a table
|
||||||
* @param field string Field to update
|
* @param field string Field to update
|
||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
@ -94,7 +193,7 @@ class Base {
|
|||||||
if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute())
|
if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
$this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id");
|
$this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id");
|
||||||
return false;
|
$this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -22,6 +22,12 @@ class BitcoinWrapper extends BitcoinClient {
|
|||||||
/**
|
/**
|
||||||
* Wrap variouns methods to add caching
|
* Wrap variouns methods to add caching
|
||||||
**/
|
**/
|
||||||
|
// Caching this, used for each can_connect call
|
||||||
|
public function getinfo() {
|
||||||
|
$this->oDebug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
|
return $this->memcache->setCache(__FUNCTION__, parent::getinfo(), 30);
|
||||||
|
}
|
||||||
public function getblockcount() {
|
public function getblockcount() {
|
||||||
$this->oDebug->append("STA " . __METHOD__, 4);
|
$this->oDebug->append("STA " . __METHOD__, 4);
|
||||||
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
@ -48,15 +54,21 @@ class BitcoinWrapper extends BitcoinClient {
|
|||||||
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
try {
|
try {
|
||||||
$dNetworkHashrate = $this->query('getmininginfo');
|
$dNetworkHashrate = $this->query('getmininginfo');
|
||||||
if (is_array($dNetworkHashrate) && array_key_exists('networkhashps', $dNetworkHashrate)) {
|
if (is_array($dNetworkHashrate)) {
|
||||||
$dNetworkHashrate = $dNetworkHashrate['networkhashps'];
|
if (array_key_exists('networkhashps', $dNetworkHashrate)) {
|
||||||
} else if (is_array($dNetworkHashrate) && array_key_exists('hashespersec', $dNetworkHashrate)) {
|
$dNetworkHashrate = $dNetworkHashrate['networkhashps'];
|
||||||
$dNetworkHashrate = $dNetworkHashrate['hashespersec'];
|
} else if (array_key_exists('hashespersec', $dNetworkHashrate)) {
|
||||||
} else if (is_array($dNetworkHashrate) && array_key_exists('netmhashps', $dNetworkHashrate)) {
|
$dNetworkHashrate = $dNetworkHashrate['hashespersec'];
|
||||||
$dNetworkHashrate = $dNetworkHashrate['netmhashps'] * 1000 * 1000;
|
} else if (array_key_exists('netmhashps', $dNetworkHashrate)) {
|
||||||
|
$dNetworkHashrate = $dNetworkHashrate['netmhashps'] * 1000 * 1000;
|
||||||
|
} else {
|
||||||
|
// Unsupported implementation
|
||||||
|
$dNetworkHashrate = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return false;
|
// getmininginfo does not exist, cache for an hour
|
||||||
|
return $this->memcache->setCache(__FUNCTION__, 0, 3600);
|
||||||
}
|
}
|
||||||
return $this->memcache->setCache(__FUNCTION__, $dNetworkHashrate, 30);
|
return $this->memcache->setCache(__FUNCTION__, $dNetworkHashrate, 30);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,32 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
die('Hacking attempt');
|
|
||||||
|
|
||||||
class Block {
|
class Block extends Base {
|
||||||
private $sError = '';
|
protected $table = 'blocks';
|
||||||
private $table = 'blocks';
|
|
||||||
// This defines each block
|
|
||||||
public $height, $blockhash, $confirmations, $time, $accounted;
|
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $config) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->debug->append("Instantiated Block class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and set methods
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
public function getTableName() {
|
|
||||||
return $this->table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific method to fetch the latest block found
|
* Specific method to fetch the latest block found
|
||||||
@ -35,13 +13,9 @@ class Block {
|
|||||||
**/
|
**/
|
||||||
public function getLast() {
|
public function getLast() {
|
||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height DESC LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height DESC LIMIT 1");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
$stmt->close();
|
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
}
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,7 +27,31 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE height = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE height = ? LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $height) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $height) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
return false;
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a specific block, by share_id
|
||||||
|
* @param share_id int Blocks share_id
|
||||||
|
* @return data array Block information from DB
|
||||||
|
**/
|
||||||
|
public function getBlockByShareId($share_id) {
|
||||||
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE share_id = ? LIMIT 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $share_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_assoc();
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a specific block, by id
|
||||||
|
* @param share_id int Blocks share_id
|
||||||
|
* @return data array Block information from DB
|
||||||
|
**/
|
||||||
|
public function getBlockById($id) {
|
||||||
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE id = ? LIMIT 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_assoc();
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +63,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->table LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->table LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->share_id;
|
return $result->fetch_object()->share_id;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -77,7 +75,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE ISNULL(share_id) ORDER BY height $order");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE ISNULL(share_id) ORDER BY height $order");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +87,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE accounted = 0 ORDER BY height $order");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE accounted = 0 ORDER BY height $order");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -101,7 +99,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT COUNT(id) AS blocks FROM $this->table");
|
$stmt = $this->mysqli->prepare("SELECT COUNT(id) AS blocks FROM $this->table");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return (int)$result->fetch_object()->blocks;
|
return (int)$result->fetch_object()->blocks;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,7 +111,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT AVG(x.shares) AS average FROM (SELECT shares FROM $this->table WHERE height <= ? ORDER BY height DESC LIMIT ?) AS x");
|
$stmt = $this->mysqli->prepare("SELECT AVG(x.shares) AS average FROM (SELECT shares FROM $this->table WHERE height <= ? ORDER BY height DESC LIMIT ?) AS x");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $height, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $height, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return (float)$result->fetch_object()->average;
|
return (float)$result->fetch_object()->average;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,7 +123,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT AVG(x.amount) AS average FROM (SELECT amount FROM $this->table ORDER BY height DESC LIMIT ?) AS x");
|
$stmt = $this->mysqli->prepare("SELECT AVG(x.amount) AS average FROM (SELECT amount FROM $this->table ORDER BY height DESC LIMIT ?) AS x");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $limit) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return (float)$result->fetch_object()->average;
|
return (float)$result->fetch_object()->average;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,7 +135,7 @@ class Block {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE confirmations < ? AND confirmations > -1");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE confirmations < ? AND confirmations > -1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $confirmations) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $confirmations) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,13 +146,9 @@ class Block {
|
|||||||
**/
|
**/
|
||||||
public function setConfirmations($block_id, $confirmations) {
|
public function setConfirmations($block_id, $confirmations) {
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET confirmations = ? WHERE id = ?");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET confirmations = ? WHERE id = ?");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $confirmations, $block_id) && $stmt->execute())
|
||||||
$stmt->bind_param("ii", $confirmations, $block_id) or die($stmt->error);
|
|
||||||
$stmt->execute() or die("Failed");
|
|
||||||
$stmt->close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,13 +158,9 @@ class Block {
|
|||||||
**/
|
**/
|
||||||
public function getAll($order='DESC') {
|
public function getAll($order='DESC') {
|
||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height $order");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table ORDER BY height $order");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
$stmt->close();
|
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
}
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,50 +170,21 @@ class Block {
|
|||||||
**/
|
**/
|
||||||
public function addBlock($block) {
|
public function addBlock($block) {
|
||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (height, blockhash, confirmations, amount, difficulty, time) VALUES (?, ?, ?, ?, ?, ?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (height, blockhash, confirmations, amount, difficulty, time) VALUES (?, ?, ?, ?, ?, ?)");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('isiddi', $block['height'], $block['blockhash'], $block['confirmations'], $block['amount'], $block['difficulty'], $block['time']) && $stmt->execute())
|
||||||
$stmt->bind_param('isiddi', $block['height'], $block['blockhash'], $block['confirmations'], $block['amount'], $block['difficulty'], $block['time']);
|
|
||||||
if (!$stmt->execute()) {
|
|
||||||
$this->debug->append("Failed to execute statement: " . $stmt->error);
|
|
||||||
$this->setErrorMessage($stmt->error);
|
|
||||||
$stmt->close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$stmt->close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLastUpstreamId() {
|
|
||||||
$stmt = $this->mysqli->prepare("
|
|
||||||
SELECT MAX(share_id) AS share_id FROM $this->table
|
|
||||||
");
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $stmt->bind_result($share_id) && $stmt->fetch())
|
|
||||||
return $share_id ? $share_id : 0;
|
|
||||||
// Catchall
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a single column within a single row
|
* Get our last inserted upstream ID from table
|
||||||
* @param block_id int Block ID to update
|
* @param none
|
||||||
* @param field string Column name to update
|
* @return mixed upstream ID or 0, false on error
|
||||||
* @param value string Value to insert
|
|
||||||
* @return bool
|
|
||||||
**/
|
**/
|
||||||
private function updateSingle($block_id, $field, $value) {
|
public function getLastUpstreamId() {
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET $field = ? WHERE id = ?");
|
$stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->table");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->execute() && $stmt->bind_result($share_id) && $stmt->fetch())
|
||||||
$stmt->bind_param('ii', $value, $block_id);
|
return $share_id ? $share_id : 0;
|
||||||
if (!$stmt->execute()) {
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to update block ID $block_id with finder ID $account_id");
|
|
||||||
$stmt->close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$stmt->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,7 +194,19 @@ class Block {
|
|||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function setFinder($block_id, $account_id=NULL) {
|
public function setFinder($block_id, $account_id=NULL) {
|
||||||
return $this->updateSingle($block_id, 'account_id', $account_id);
|
$field = array( 'name' => 'account_id', 'value' => $account_id, 'type' => 'i' );
|
||||||
|
return $this->updateSingle($block_id, $field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set finding worker of a block
|
||||||
|
* @param block_id int Block ID
|
||||||
|
* @param worker_id int Worker ID of finder
|
||||||
|
* @return bool
|
||||||
|
**/
|
||||||
|
public function setFindingWorker($block_id, $worker=NULL) {
|
||||||
|
$field = array( 'name' => 'worker_name', 'value' => $worker, 'type' => 's' );
|
||||||
|
return $this->updateSingle($block_id, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,7 +216,8 @@ class Block {
|
|||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function setShareId($block_id, $share_id) {
|
public function setShareId($block_id, $share_id) {
|
||||||
return $this->updateSingle($block_id, 'share_id', $share_id);
|
$field = array( 'name' => 'share_id', 'value' => $share_id, 'type' => 'i');
|
||||||
|
return $this->updateSingle($block_id, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -253,7 +227,8 @@ class Block {
|
|||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function setShares($block_id, $shares=NULL) {
|
public function setShares($block_id, $shares=NULL) {
|
||||||
return $this->updateSingle($block_id, 'shares', $shares);
|
$field = array( 'name' => 'shares', 'value' => $shares, 'type' => 'i');
|
||||||
|
return $this->updateSingle($block_id, $field);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,21 +238,14 @@ class Block {
|
|||||||
**/
|
**/
|
||||||
public function setAccounted($block_id=NULL) {
|
public function setAccounted($block_id=NULL) {
|
||||||
if (empty($block_id)) return false;
|
if (empty($block_id)) return false;
|
||||||
return $this->updateSingle($block_id, 'accounted', 1);
|
$field = array( 'name' => 'accounted', 'value' => 1, 'type' => 'i');
|
||||||
}
|
return $this->updateSingle($block_id, $field);
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function
|
|
||||||
**/
|
|
||||||
private function checkStmt($bState) {
|
|
||||||
if ($bState ===! true) {
|
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatically load our class for furhter usage
|
// Automatically load our class for furhter usage
|
||||||
$block = new Block($debug, $mysqli, $config);
|
$block = new Block();
|
||||||
|
$block->setDebug($debug);
|
||||||
|
$block->setMysql($mysqli);
|
||||||
|
$block->setConfig($config);
|
||||||
|
$block->setErrorCodes($aErrorCodes);
|
||||||
|
|||||||
@ -16,9 +16,7 @@ class Invitation extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ?");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ?");
|
||||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
$this->setErrorMessage('Unable to fetch invitiations send from your account');
|
$this->sqlError('E0021');
|
||||||
$this->debug->append('Failed to fetch invitations from database: ' . $this->mysqli->errro);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,9 +29,7 @@ class Invitation extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT count(id) AS total FROM $this->table WHERE account_id = ?");
|
$stmt = $this->mysqli->prepare("SELECT count(id) AS total FROM $this->table WHERE account_id = ?");
|
||||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $stmt->bind_result($total) && $stmt->fetch())
|
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $stmt->bind_result($total) && $stmt->fetch())
|
||||||
return $total;
|
return $total;
|
||||||
$this->setErrorMessage('Unable to fetch invitiations send from your account');
|
$this->sqlError('E0021');
|
||||||
$this->debug->append('Failed to fetch invitations from database: ' . $this->mysqli->errro);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +61,7 @@ class Invitation extends Base {
|
|||||||
**/
|
**/
|
||||||
public function setActivated($token_id) {
|
public function setActivated($token_id) {
|
||||||
if (!$iInvitationId = $this->getByTokenId($token_id)) {
|
if (!$iInvitationId = $this->getByTokenId($token_id)) {
|
||||||
$this->setErrorMessage('Unable to convert token ID to invitation ID');
|
$this->setErrorMessage($this->getErrorMsg('E0030'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$field = array('name' => 'is_activated', 'type' => 'i', 'value' => 1);
|
$field = array('name' => 'is_activated', 'type' => 'i', 'value' => 1);
|
||||||
@ -84,8 +80,9 @@ class Invitation extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table ( account_id, email, token_id ) VALUES ( ?, ?, ?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table ( account_id, email, token_id ) VALUES ( ?, ?, ?)");
|
||||||
if ($stmt && $stmt->bind_param('isi', $account_id, $email, $token_id) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('isi', $account_id, $email, $token_id) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
$this->sqlError('E0022');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an invitation out to a user
|
* Send an invitation out to a user
|
||||||
* Uses the mail class to send mails
|
* Uses the mail class to send mails
|
||||||
@ -97,39 +94,37 @@ class Invitation extends Base {
|
|||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
// Check data input
|
// Check data input
|
||||||
if (empty($aData['email']) || !filter_var($aData['email'], FILTER_VALIDATE_EMAIL)) {
|
if (empty($aData['email']) || !filter_var($aData['email'], FILTER_VALIDATE_EMAIL)) {
|
||||||
$this->setErrorMessage( 'Invalid e-mail address' );
|
$this->setErrorMessage($this->getErrorMsg('E0023'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (preg_match('/[^a-z_\.\!\?\-0-9 ]/i', $aData['message'])) {
|
if (preg_match('/[^a-z_\.\!\?\-0-9 ]/i', $aData['message'])) {
|
||||||
$this->setErrorMessage('Message may only contain alphanumeric characters');
|
$this->setErrorMessage($this->getErrorMsg('E0024'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Ensure this invitation does not exist yet nor do we have an account with that email
|
// Ensure this invitation does not exist yet nor do we have an account with that email
|
||||||
if ($this->user->getEmail($aData['email'])) {
|
if ($this->user->getEmail($aData['email'])) {
|
||||||
$this->setErrorMessage('This email is already registered as an account');
|
$this->setErrorMessage($this->getErrorMsg('E0025'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($this->getByEmail($aData['email'])) {
|
if ($this->getByEmail($aData['email'])) {
|
||||||
$this->setErrorMessage('A pending invitation for this address already exists');
|
$this->setErrorMessage($this->getErrorMsg('E0026'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!$aData['token'] = $this->token->createToken('invitation', $account_id)) {
|
if (!$aData['token'] = $this->token->createToken('invitation', $account_id)) {
|
||||||
$this->setErrorMessage('Unable to generate invitation token: ' . $this->token->getError());
|
$this->setErrorMessage($this->getErrorMsg('E0027', $this->token->getError()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$aData['username'] = $this->user->getUserName($account_id);
|
$aData['username'] = $this->user->getUserName($account_id);
|
||||||
$aData['subject'] = 'Pending Invitation';
|
$aData['subject'] = 'Pending Invitation';
|
||||||
if ($this->mail->sendMail('invitations/body', $aData)) {
|
if ($this->mail->sendMail('invitations/body', $aData)) {
|
||||||
$aToken = $this->token->getToken($aData['token']);
|
$aToken = $this->token->getToken($aData['token']);
|
||||||
if (!$this->createInvitation($account_id, $aData['email'], $aToken['id'])) {
|
if (!$this->createInvitation($account_id, $aData['email'], $aToken['id']))
|
||||||
$this->setErrorMessage('Unable to create invitation record');
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
$this->setErrorMessage('Unable to send email to recipient');
|
$this->setErrorMessage($this->getErrorMsg('E0028'));
|
||||||
}
|
}
|
||||||
$this->setErrorMessage('Unable to send invitation');
|
$this->setErrorMessage($this->getErrorMsg('E0029'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,5 +137,5 @@ $invitation->setMail($mail);
|
|||||||
$invitation->setUser($user);
|
$invitation->setUser($user);
|
||||||
$invitation->setToken($oToken);
|
$invitation->setToken($oToken);
|
||||||
$invitation->setConfig($config);
|
$invitation->setConfig($config);
|
||||||
|
$invitation->setErrorCodes($aErrorCodes);
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -5,16 +5,6 @@ if (!defined('SECURITY'))
|
|||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class Mail extends Base {
|
class Mail extends Base {
|
||||||
function checkStmt($bState) {
|
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
|
||||||
if ($bState ===! true) {
|
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mail form contact site admin
|
* Mail form contact site admin
|
||||||
* @param senderName string senderName
|
* @param senderName string senderName
|
||||||
@ -28,19 +18,19 @@ class Mail extends Base {
|
|||||||
public function contactform($senderName, $senderEmail, $senderSubject, $senderMessage) {
|
public function contactform($senderName, $senderEmail, $senderSubject, $senderMessage) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderName)) {
|
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderName)) {
|
||||||
$this->setErrorMessage('Username may only contain alphanumeric characters');
|
$this->setErrorMessage($this->getErrorMsg('E0024'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (empty($senderEmail) || !filter_var($senderEmail, FILTER_VALIDATE_EMAIL)) {
|
if (empty($senderEmail) || !filter_var($senderEmail, FILTER_VALIDATE_EMAIL)) {
|
||||||
$this->setErrorMessage( 'Invalid e-mail address' );
|
$this->setErrorMessage($this->getErrorMsg('E0023'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderSubject)) {
|
if (preg_match('/[^a-z_\.\!\?\-0-9\\s ]/i', $senderSubject)) {
|
||||||
$this->setErrorMessage('Subject may only contain alphanumeric characters');
|
$this->setErrorMessage($this->getErrorMsg('E0034'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (strlen(strip_tags($senderMessage)) < strlen($senderMessage)) {
|
if (strlen(strip_tags($senderMessage)) < strlen($senderMessage)) {
|
||||||
$this->setErrorMessage('Your message may only contain alphanumeric characters');
|
$this->setErrorMessage($this->getErrorMsg('E0024'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$aData['senderName'] = $senderName;
|
$aData['senderName'] = $senderName;
|
||||||
@ -58,16 +48,28 @@ class Mail extends Base {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a mail with templating via Smarty
|
||||||
|
* @param template string Template name within the mail folder, no extension
|
||||||
|
* @param aData array Data array with some required fields
|
||||||
|
* SUBJECT : Mail Subject
|
||||||
|
* email : Destination address
|
||||||
|
**/
|
||||||
public function sendMail($template, $aData) {
|
public function sendMail($template, $aData) {
|
||||||
|
// Make sure we don't load a cached filed
|
||||||
|
$this->smarty->clearCache(BASEPATH . 'templates/mail/' . $template . '.tpl');
|
||||||
|
$this->smarty->clearCache(BASEPATH . 'templates/mail/subject.tpl');
|
||||||
$this->smarty->assign('WEBSITENAME', $this->setting->getValue('website_name'));
|
$this->smarty->assign('WEBSITENAME', $this->setting->getValue('website_name'));
|
||||||
$this->smarty->assign('SUBJECT', $aData['subject']);
|
$this->smarty->assign('SUBJECT', $aData['subject']);
|
||||||
$this->smarty->assign('DATA', $aData);
|
$this->smarty->assign('DATA', $aData);
|
||||||
$headers = 'From: Website Administration <' . $this->setting->getValue('website_email') . ">\n";
|
$headers = 'From: Website Administration <' . $this->setting->getValue('website_email') . ">\n";
|
||||||
$headers .= "MIME-Version: 1.0\n";
|
$headers .= "MIME-Version: 1.0\n";
|
||||||
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
|
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
|
||||||
|
if (strlen(@$aData['senderName']) > 0 && @strlen($aData['senderEmail']) > 0 )
|
||||||
|
$headers .= 'Reply-To: ' . $aData['senderName'] . ' <' . $aData['senderEmail'] . ">\n";
|
||||||
if (mail($aData['email'], $this->smarty->fetch(BASEPATH . 'templates/mail/subject.tpl'), $this->smarty->fetch(BASEPATH . 'templates/mail/' . $template . '.tpl'), $headers))
|
if (mail($aData['email'], $this->smarty->fetch(BASEPATH . 'templates/mail/subject.tpl'), $this->smarty->fetch(BASEPATH . 'templates/mail/' . $template . '.tpl'), $headers))
|
||||||
return true;
|
return true;
|
||||||
$this->setErrorMessage('Unable to send mail');
|
$this->setErrorMessage($this->sqlError('E0031'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,4 +81,5 @@ $mail->setMysql($mysqli);
|
|||||||
$mail->setSmarty($smarty);
|
$mail->setSmarty($smarty);
|
||||||
$mail->setConfig($config);
|
$mail->setConfig($config);
|
||||||
$mail->setSetting($setting);
|
$mail->setSetting($setting);
|
||||||
|
$mail->setErrorCodes($aErrorCodes);
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -1,14 +1,65 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
die('Hacking attempt');
|
|
||||||
|
|
||||||
class Monitoring {
|
class Monitoring extends Base {
|
||||||
public function __construct($debug, $mysqli) {
|
protected $table = 'monitoring';
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
/**
|
||||||
$this->table = 'monitoring';
|
* Store Uptime Robot status information as JSON in settings table
|
||||||
|
* @param none
|
||||||
|
* @return bool true on success, false on error
|
||||||
|
**/
|
||||||
|
public function storeUptimeRobotStatus() {
|
||||||
|
if ($api_keys = $this->setting->getValue('monitoring_uptimerobot_api_keys')) {
|
||||||
|
$aJSONData = array();
|
||||||
|
$url = 'http://api.uptimerobot.com';
|
||||||
|
$aMonitors = explode(',', $api_keys);
|
||||||
|
foreach ($aMonitors as $aData) {
|
||||||
|
$temp = explode('|', $aData);
|
||||||
|
$aMonitor['api_key'] = $temp[0];
|
||||||
|
$aMonitor['monitor_id'] = $temp[1];
|
||||||
|
$target = '/getMonitors?apiKey=' . $aMonitor['api_key'] . '&monitors=' . $aMonitor['monitor_id'] . '&format=json&noJsonCallback=1&customUptimeRatio=1-7-30&logs=1';
|
||||||
|
$aMonitorStatus = $this->tools->getApi($url, $target);
|
||||||
|
if (!$aMonitorStatus || @$aMonitorStatus['stat'] == 'fail') {
|
||||||
|
if (is_array($aMonitorStatus) && array_key_exists('message', @$aMonitorStatus)) {
|
||||||
|
$this->setErrorMessage($this->getErrorMsg('E0032', $aMonitorStatus['message']));
|
||||||
|
} else {
|
||||||
|
$this->setErrorMessage($this->getErrorMsg('E0032', $this->tools->getError()));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$aMonitorStatus['monitors']['monitor'][0]['customuptimeratio'] = explode('-', $aMonitorStatus['monitors']['monitor'][0]['customuptimeratio']);
|
||||||
|
$aAllMonitorsStatus[] = $aMonitorStatus['monitors']['monitor'][0];
|
||||||
|
}
|
||||||
|
if (!$this->setting->setValue('monitoring_uptimerobot_status', json_encode($aAllMonitorsStatus)) || !$this->setting->setValue('monitoring_uptimerobot_lastcheck', time())) {
|
||||||
|
$this->setErrorMessage($this->getErrorMsg('E0033'), $setting->getError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch Uptime Robot Status from settings table
|
||||||
|
* @param none
|
||||||
|
* @return array Data on success, false on failure
|
||||||
|
**/
|
||||||
|
public function getUptimeRobotStatus() {
|
||||||
|
if ($json = $this->setting->getValue('monitoring_uptimerobot_status'))
|
||||||
|
return json_decode($json, true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that our cron is currently activated
|
||||||
|
* @param name string Cronjob name
|
||||||
|
* @return bool true or false
|
||||||
|
**/
|
||||||
|
public function isDisabled($name) {
|
||||||
|
$aStatus = $this->getStatus($name . '_disabled');
|
||||||
|
return $aStatus['value'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,8 +72,7 @@ class Monitoring {
|
|||||||
if ($query && $query->bind_param('s', $name) && $query->execute() && $result = $query->get_result()) {
|
if ($query && $query->bind_param('s', $name) && $query->execute() && $result = $query->get_result()) {
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
} else {
|
} else {
|
||||||
$this->debug->append("Failed to fetch variable $name from $this->table");
|
$this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
@ -44,6 +94,41 @@ class Monitoring {
|
|||||||
$this->debug->append("Failed to set $name to $value");
|
$this->debug->append("Failed to set $name to $value");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End cronjob with an error message
|
||||||
|
* @param cron_name string Cronjob Name
|
||||||
|
* @param msgCode string Message code as stored in error_codes array
|
||||||
|
* @param exitCode int Exit code to pass on to exit function and monitor report
|
||||||
|
* @param fatal boolean Should we exit out entirely
|
||||||
|
* @return none
|
||||||
|
**/
|
||||||
|
public function endCronjob($cron_name, $msgCode, $exitCode=0, $fatal=false, $mail=true) {
|
||||||
|
$this->setStatus($cron_name . "_active", "yesno", 0);
|
||||||
|
$this->setStatus($cron_name . "_message", "message", $this->getErrorMsg($msgCode));
|
||||||
|
$this->setStatus($cron_name . "_status", "okerror", $exitCode);
|
||||||
|
$this->setStatus($cron_name . "_endtime", "date", time());
|
||||||
|
if ($mail) {
|
||||||
|
$aMailData = array(
|
||||||
|
'email' => $this->setting->getValue('system_error_email'),
|
||||||
|
'subject' => 'Cronjob Failure',
|
||||||
|
'Error Code' => $msgCode,
|
||||||
|
'Error Message' => $this->getErrorMsg($msgCode)
|
||||||
|
);
|
||||||
|
if (!$this->mail->sendMail('notifications/error', $aMailData))
|
||||||
|
$this->setErrorMessage('Failed to send mail notification');
|
||||||
|
}
|
||||||
|
if ($fatal) {
|
||||||
|
if ($exitCode != 0) $this->setStatus($cron_name . "_disabled", "yesno", 1);
|
||||||
|
exit($exitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$monitoring = new Monitoring($debug, $mysqli);
|
$monitoring = new Monitoring();
|
||||||
|
$monitoring->setErrorCodes($aErrorCodes);
|
||||||
|
$monitoring->setConfig($config);
|
||||||
|
$monitoring->setDebug($debug);
|
||||||
|
$monitoring->setMail($mail);
|
||||||
|
$monitoring->setMysql($mysqli);
|
||||||
|
$monitoring->setSetting($setting);
|
||||||
|
|||||||
@ -5,13 +5,23 @@ if (!defined('SECURITY'))
|
|||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class News extends Base {
|
class News extends Base {
|
||||||
var $table = 'news';
|
protected $table = 'news';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get activation status of post
|
||||||
|
* @param id int News ID
|
||||||
|
* @return bool true or false
|
||||||
|
**/
|
||||||
public function getActive($id) {
|
public function getActive($id) {
|
||||||
$this->debug->append("STA " . __METHOD__, 5);
|
$this->debug->append("STA " . __METHOD__, 5);
|
||||||
return $this->getSingle($id, 'active', 'id');
|
return $this->getSingle($id, 'active', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch activation status
|
||||||
|
* @param id int News ID
|
||||||
|
* @return bool true or false
|
||||||
|
**/
|
||||||
public function toggleActive($id) {
|
public function toggleActive($id) {
|
||||||
$this->debug->append("STA " . __METHOD__, 5);
|
$this->debug->append("STA " . __METHOD__, 5);
|
||||||
$field = array('name' => 'active', 'type' => 'i', 'value' => !$this->getActive($id));
|
$field = array('name' => 'active', 'type' => 'i', 'value' => !$this->getActive($id));
|
||||||
@ -26,8 +36,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT n.*, a.username AS author FROM $this->table AS n LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = n.account_id WHERE active = 1 ORDER BY time DESC");
|
$stmt = $this->mysqli->prepare("SELECT n.*, a.username AS author FROM $this->table AS n LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = n.account_id WHERE active = 1 ORDER BY time DESC");
|
||||||
if ($stmt && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->sqlError('E0040');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,8 +47,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT n.*, a.username AS author FROM $this->table AS n LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = n.account_id ORDER BY time DESC");
|
$stmt = $this->mysqli->prepare("SELECT n.*, a.username AS author FROM $this->table AS n LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = n.account_id ORDER BY time DESC");
|
||||||
if ($stmt && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->sqlError('E0039');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,8 +58,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE id = ?");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE id = ?");
|
||||||
if ($stmt && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
// Catchall
|
return $this->sqlError('E0038');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,8 +69,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET content = ?, header = ?, active = ? WHERE id = ?");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET content = ?, header = ?, active = ? WHERE id = ?");
|
||||||
if ($stmt && $stmt->bind_param('ssii', $content, $header, $active, $id) && $stmt->execute() && $stmt->affected_rows == 1)
|
if ($stmt && $stmt->bind_param('ssii', $content, $header, $active, $id) && $stmt->execute() && $stmt->affected_rows == 1)
|
||||||
return true;
|
return true;
|
||||||
$this->setErrorMessage("Failed to update news entry $id");
|
return $this->sqlError('E0037');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteNews($id) {
|
public function deleteNews($id) {
|
||||||
@ -72,8 +78,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id = ?");
|
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id = ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $stmt->affected_rows == 1)
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $stmt->affected_rows == 1)
|
||||||
return true;
|
return true;
|
||||||
$this->setErrorMessage("Failed to delete news entry $id");
|
return $this->sqlError('E0036');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,9 +94,7 @@ class News extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, header, content, active) VALUES (?,?,?,?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, header, content, active) VALUES (?,?,?,?)");
|
||||||
if ($stmt && $stmt->bind_param('issi', $account_id, $aData['header'], $aData['content'], $active) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('issi', $account_id, $aData['header'], $aData['content'], $active) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
$this->debug->append("Failed to add news: " . $this->mysqli->error);
|
return $this->sqlError('E0035');
|
||||||
$this->setErrorMessage("Unable to add new news: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,9 +27,7 @@ class Notification extends Mail {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE data = ? AND active = 1 LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE data = ? AND active = 1 LIMIT 1");
|
||||||
if ($stmt && $stmt->bind_param('s', $data) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows == 1)
|
if ($stmt && $stmt->bind_param('s', $data) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows == 1)
|
||||||
return true;
|
return true;
|
||||||
// Catchall
|
return $this->sqlError('E0041');
|
||||||
// Does not seem to have a notification set
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +38,7 @@ class Notification extends Mail {
|
|||||||
$stmt =$this->mysqli->prepare("SELECT id, data FROM $this->table WHERE active = 1 AND type = ?");
|
$stmt =$this->mysqli->prepare("SELECT id, data FROM $this->table WHERE active = 1 AND type = ?");
|
||||||
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->sqlError('E0042');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,9 +53,7 @@ class Notification extends Mail {
|
|||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, type, data, active) VALUES (?, ?,?,1)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, type, data, active) VALUES (?, ?,?,1)");
|
||||||
if ($stmt && $stmt->bind_param('iss', $account_id, $type, $data) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('iss', $account_id, $type, $data) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
$this->debug->append("Failed to add notification for $type with $data: " . $this->mysqli->error);
|
return $this->sqlError('E0043');
|
||||||
$this->setErrorMessage("Unable to add new notification " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,8 +66,7 @@ class Notification extends Mail {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? ORDER BY time DESC");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? ORDER BY time DESC");
|
||||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->getError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,10 +85,7 @@ class Notification extends Mail {
|
|||||||
return $aData;
|
return $aData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError('E0045');
|
||||||
$this->setErrorMessage('Unable to fetch notification settings');
|
|
||||||
$this->debug->append('Failed fetching notification settings for ' . $account_id . ': ' . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,8 +99,7 @@ class Notification extends Mail {
|
|||||||
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError('E0046');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,7 +132,7 @@ class Notification extends Mail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($failed > 0) {
|
if ($failed > 0) {
|
||||||
$this->setErrorMessage('Failed to update ' . $failed . ' settings');
|
$this->setErrorMessage($this->getErrorMsg('E0047', $failed));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -183,4 +173,5 @@ $notification->setMysql($mysqli);
|
|||||||
$notification->setSmarty($smarty);
|
$notification->setSmarty($smarty);
|
||||||
$notification->setConfig($config);
|
$notification->setConfig($config);
|
||||||
$notification->setSetting($setting);
|
$notification->setSetting($setting);
|
||||||
|
$notification->setErrorCodes($aErrorCodes);
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
if (!defined('SECURITY')) die('Hacking attempt');
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
class Payout Extends Base {
|
class Payout Extends Base {
|
||||||
var $table = 'payouts';
|
protected $table = 'payouts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the user has an active payout request already
|
* Check if the user has an active payout request already
|
||||||
@ -15,7 +15,7 @@ class Payout Extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE completed = 0 AND account_id = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE completed = 0 AND account_id = ? LIMIT 1");
|
||||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute( )&& $stmt->store_result() && $stmt->num_rows > 0)
|
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute( )&& $stmt->store_result() && $stmt->num_rows > 0)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return $this->sqlError('E0048');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +27,7 @@ class Payout Extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE completed = 0");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE completed = 0");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError('E0050');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,9 +40,7 @@ class Payout Extends Base {
|
|||||||
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute()) {
|
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute()) {
|
||||||
return $stmt->insert_id;
|
return $stmt->insert_id;
|
||||||
}
|
}
|
||||||
$this->setErrorMessage('Unable to create new payout request');
|
return $this->sqlError('E0049');
|
||||||
$this->debug->append('Failed to create new payout request in database: ' . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,10 +52,13 @@ class Payout Extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET completed = 1 WHERE id = ?");
|
$stmt = $this->mysqli->prepare("UPDATE $this->table SET completed = 1 WHERE id = ?");
|
||||||
if ($stmt && $stmt->bind_param('i', $id) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('i', $id) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return $this->sqlError('E0051');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$oPayout = new Payout();
|
$oPayout = new Payout();
|
||||||
$oPayout->setDebug($debug);
|
$oPayout->setDebug($debug);
|
||||||
$oPayout->setMysql($mysqli);
|
$oPayout->setMysql($mysqli);
|
||||||
|
$oPayout->setErrorCodes($aErrorCodes);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@ -4,41 +4,25 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class RoundStats {
|
class RoundStats extends Base {
|
||||||
private $sError = '';
|
|
||||||
private $tableTrans = 'transactions';
|
private $tableTrans = 'transactions';
|
||||||
private $tableStats = 'statistics_shares';
|
private $tableStats = 'statistics_shares';
|
||||||
private $tableBlocks = 'blocks';
|
private $tableBlocks = 'blocks';
|
||||||
private $tableUsers = 'accounts';
|
private $tableUsers = 'accounts';
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $config) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->debug->append("Instantiated RoundStats class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and set methods
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get next block for round stats
|
* Get next block for round stats
|
||||||
**/
|
**/
|
||||||
public function getNextBlock($iHeight=0) {
|
public function getNextBlock($iHeight=0) {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT height
|
SELECT height
|
||||||
FROM $this->tableBlocks
|
FROM " . $this->block->getTableName() . "
|
||||||
WHERE height > ?
|
WHERE height > ?
|
||||||
ORDER BY height ASC
|
ORDER BY height ASC
|
||||||
LIMIT 1");
|
LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->height;
|
return $result->fetch_object()->height;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,13 +31,44 @@ class RoundStats {
|
|||||||
public function getPreviousBlock($iHeight=0) {
|
public function getPreviousBlock($iHeight=0) {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT height
|
SELECT height
|
||||||
FROM $this->tableBlocks
|
FROM " . $this->block->getTableName() . "
|
||||||
WHERE height < ?
|
WHERE height < ?
|
||||||
ORDER BY height DESC
|
ORDER BY height DESC
|
||||||
LIMIT 1");
|
LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->height;
|
return $result->fetch_object()->height;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for block height
|
||||||
|
**/
|
||||||
|
public function searchForBlockHeight($iHeight=0) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT height
|
||||||
|
FROM " . $this->block->getTableName() . "
|
||||||
|
WHERE height >= ?
|
||||||
|
ORDER BY height ASC
|
||||||
|
LIMIT 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->height;
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get next block for stats paging
|
||||||
|
**/
|
||||||
|
public function getNextBlockForStats($iHeight=0, $limit=10) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT MAX(x.height) AS height
|
||||||
|
FROM (
|
||||||
|
SELECT height FROM " . $this->block->getTableName() . "
|
||||||
|
WHERE height >= ?
|
||||||
|
ORDER BY height ASC LIMIT ?
|
||||||
|
) AS x");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->height;
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,17 +76,19 @@ class RoundStats {
|
|||||||
* @param height int Block Height
|
* @param height int Block Height
|
||||||
* @return data array Block information from DB
|
* @return data array Block information from DB
|
||||||
**/
|
**/
|
||||||
public function getDetailsForBlockHeight($iHeight=0, $isAdmin=0) {
|
public function getDetailsForBlockHeight($iHeight=0) {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
b.id, height, blockhash, amount, confirmations, difficulty, FROM_UNIXTIME(time) as time, shares,
|
b.id, height, blockhash, amount, confirmations, difficulty, FROM_UNIXTIME(time) as time, shares,
|
||||||
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS finder
|
IF(a.is_anonymous, 'anonymous', a.username) AS finder,
|
||||||
FROM $this->tableBlocks as b
|
ROUND((difficulty * 65535) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares,
|
||||||
LEFT JOIN $this->tableUsers AS a ON b.account_id = a.id
|
(time - (SELECT time FROM $this->tableBlocks WHERE height < ? ORDER BY height DESC LIMIT 1)) AS round_time
|
||||||
WHERE b.height = ? LIMIT 1");
|
FROM " . $this->block->getTableName() . " as b
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON b.account_id = a.id
|
||||||
|
WHERE b.height = ? LIMIT 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,22 +96,68 @@ class RoundStats {
|
|||||||
* @param height int Block Height
|
* @param height int Block Height
|
||||||
* @return data array Block information from DB
|
* @return data array Block information from DB
|
||||||
**/
|
**/
|
||||||
public function getRoundStatsForAccounts($iHeight=0, $isAdmin=0) {
|
public function getRoundStatsForAccounts($iHeight=0) {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
|
a.id,
|
||||||
|
a.username,
|
||||||
|
a.is_anonymous,
|
||||||
s.valid,
|
s.valid,
|
||||||
s.invalid
|
s.invalid
|
||||||
FROM $this->tableStats AS s
|
FROM " . $this->statistics->getTableName() . " AS s
|
||||||
LEFT JOIN $this->tableBlocks AS b ON s.block_id = b.id
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON s.block_id = b.id
|
||||||
LEFT JOIN $this->tableUsers AS a ON a.id = s.account_id
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = s.account_id
|
||||||
WHERE b.height = ?
|
WHERE b.height = ?
|
||||||
GROUP BY username ASC
|
GROUP BY username ASC
|
||||||
ORDER BY valid DESC
|
ORDER BY valid DESC
|
||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$aData[$row['id']] = $row;
|
||||||
|
}
|
||||||
|
return $aData;
|
||||||
|
}
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pplns statistics for round block height
|
||||||
|
* @param height int Block Height
|
||||||
|
* @return data array Block information from DB
|
||||||
|
**/
|
||||||
|
public function getPPLNSRoundStatsForAccounts($iHeight=0) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
a.username,
|
||||||
|
a.is_anonymous,
|
||||||
|
s.pplns_valid,
|
||||||
|
s.pplns_invalid
|
||||||
|
FROM " . $this->statistics->getTableName() . " AS s
|
||||||
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON s.block_id = b.id
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = s.account_id
|
||||||
|
WHERE b.height = ?
|
||||||
|
GROUP BY username ASC
|
||||||
|
ORDER BY pplns_valid DESC
|
||||||
|
");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get total valid pplns shares for block height
|
||||||
|
**/
|
||||||
|
public function getPPLNSRoundShares($iHeight=0) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
SUM(s.pplns_valid) AS pplns_valid
|
||||||
|
FROM " . $this->statistics->getTableName() . " AS s
|
||||||
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON s.block_id = b.id
|
||||||
|
WHERE b.height = ?
|
||||||
|
");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->pplns_valid;
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,23 +165,25 @@ class RoundStats {
|
|||||||
* @param height int Block Height
|
* @param height int Block Height
|
||||||
* @return data array Block round transactions
|
* @return data array Block round transactions
|
||||||
**/
|
**/
|
||||||
public function getAllRoundTransactions($iHeight=0, $admin) {
|
public function getAllRoundTransactions($iHeight=0) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
t.id AS id,
|
t.id AS id,
|
||||||
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
|
a.id AS uid,
|
||||||
|
a.username AS username,
|
||||||
|
a.is_anonymous,
|
||||||
t.type AS type,
|
t.type AS type,
|
||||||
t.amount AS amount
|
t.amount AS amount
|
||||||
FROM $this->tableTrans AS t
|
FROM " . $this->transaction->getTableName() . " AS t
|
||||||
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||||
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON t.account_id = a.id
|
||||||
WHERE b.height = ?
|
WHERE b.height = ? AND t.type = 'Credit'
|
||||||
ORDER BY id ASC");
|
ORDER BY amount DESC");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $admin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
$this->debug->append('Unable to fetch transactions');
|
$this->debug->append('Unable to fetch transactions');
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,26 +200,93 @@ class RoundStats {
|
|||||||
a.username AS username,
|
a.username AS username,
|
||||||
t.type AS type,
|
t.type AS type,
|
||||||
t.amount AS amount
|
t.amount AS amount
|
||||||
FROM $this->tableTrans AS t
|
FROM " . $this->transaction->getTableName() . " AS t
|
||||||
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||||
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON t.account_id = a.id
|
||||||
WHERE b.height = ? AND a.id = ?
|
WHERE b.height = ? AND a.id = ?
|
||||||
ORDER BY id ASC");
|
ORDER BY id ASC");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
$this->debug->append('Unable to fetch transactions');
|
$this->debug->append('Unable to fetch transactions');
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkStmt($bState) {
|
/**
|
||||||
if ($bState ===! true) {
|
* Get ALL last blocks from height for admin panel
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
**/
|
||||||
$this->setErrorMessage('Internal application Error');
|
public function getAllReportBlocksFoundHeight($iHeight=0, $limit=10) {
|
||||||
return false;
|
$stmt = $this->mysqli->prepare("
|
||||||
}
|
SELECT
|
||||||
return true;
|
height, shares
|
||||||
|
FROM " . $this->block->getTableName() . "
|
||||||
|
WHERE height <= ?
|
||||||
|
ORDER BY height DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get USER last blocks from height for admin panel
|
||||||
|
**/
|
||||||
|
public function getUserReportBlocksFoundHeight($iHeight=0, $limit=10, $iUser) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
b.height, b.shares
|
||||||
|
FROM " . $this->block->getTableName() . " AS b
|
||||||
|
LEFT JOIN " . $this->statistics->getTableName() . " AS s ON s.block_id = b.id
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = s.account_id
|
||||||
|
WHERE b.height <= ? AND a.id = ?
|
||||||
|
ORDER BY height DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $iHeight, $iUser, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get shares for block height for user admin panel
|
||||||
|
**/
|
||||||
|
public function getRoundStatsForUser($iHeight=0, $iUser) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
s.valid,
|
||||||
|
s.invalid,
|
||||||
|
s.pplns_valid,
|
||||||
|
s.pplns_invalid
|
||||||
|
FROM " . $this->statistics->getTableName() . " AS s
|
||||||
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON s.block_id = b.id
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON a.id = s.account_id
|
||||||
|
WHERE b.height = ? AND a.id = ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $iUser) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_assoc();
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get credit transactions for round block height for admin panel
|
||||||
|
**/
|
||||||
|
public function getUserRoundTransHeight($iHeight=0, $iUser) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
IFNULL(t.amount, 0) AS amount
|
||||||
|
FROM " . $this->transaction->getTableName() . " AS t
|
||||||
|
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a ON t.account_id = a.id
|
||||||
|
WHERE b.height = ? AND t.type = 'Credit' AND t.account_id = ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $iUser) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->amount;
|
||||||
|
$this->debug->append('Unable to fetch transactions');
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$roundstats = new RoundStats($debug, $mysqli, $config);
|
$roundstats = new RoundStats();
|
||||||
|
$roundstats->setDebug($debug);
|
||||||
|
$roundstats->setMysql($mysqli);
|
||||||
|
$roundstats->setConfig($config);
|
||||||
|
$roundstats->setErrorCodes($aErrorCodes);
|
||||||
|
$roundstats->setUser($user);
|
||||||
|
$roundstats->setStatistics($statistics);
|
||||||
|
$roundstats->setBlock($block);
|
||||||
|
$roundstats->setTransaction($transaction);
|
||||||
|
|||||||
@ -1,15 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
die('Hacking attempt');
|
|
||||||
|
|
||||||
class Setting {
|
class Setting extends Base {
|
||||||
public function __construct($debug, $mysqli) {
|
protected $table = 'settings';
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->table = 'settings';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a value from our table
|
* Fetch a value from our table
|
||||||
@ -17,18 +12,13 @@ class Setting {
|
|||||||
* @return value string Value
|
* @return value string Value
|
||||||
**/
|
**/
|
||||||
public function getValue($name) {
|
public function getValue($name) {
|
||||||
$query = $this->mysqli->prepare("SELECT value FROM $this->table WHERE name=? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT value FROM $this->table WHERE name = ? LIMIT 1");
|
||||||
if ($query) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $name) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
$query->bind_param('s', $name);
|
if ($result->num_rows > 0)
|
||||||
$query->execute();
|
return $result->fetch_object()->value;
|
||||||
$query->bind_result($value);
|
// Log error but return empty string
|
||||||
$query->fetch();
|
$this->sqlError();
|
||||||
$query->close();
|
return "";
|
||||||
} else {
|
|
||||||
$this->debug->append("Failed to fetch variable $name from $this->table");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,13 +31,14 @@ class Setting {
|
|||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
INSERT INTO $this->table (name, value)
|
INSERT INTO $this->table (name, value)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
ON DUPLICATE KEY UPDATE value = ?
|
ON DUPLICATE KEY UPDATE value = ?");
|
||||||
");
|
|
||||||
if ($stmt && $stmt->bind_param('sss', $name, $value, $value) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('sss', $name, $value, $value) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
$this->debug->append("Failed to set $name to $value");
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$setting = new Setting($debug, $mysqli);
|
$setting = new Setting($debug, $mysqli);
|
||||||
|
$setting->setDebug($debug);
|
||||||
|
$setting->setMysql($mysqli);
|
||||||
|
$setting->setErrorCodes($aErrorCodes);
|
||||||
|
|||||||
@ -4,32 +4,14 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class Share {
|
class Share Extends Base {
|
||||||
private $sError = '';
|
protected $table = 'shares';
|
||||||
private $table = 'shares';
|
protected $tableArchive = 'shares_archive';
|
||||||
private $tableArchive = 'shares_archive';
|
|
||||||
private $oUpstream;
|
private $oUpstream;
|
||||||
private $iLastUpstreamId;
|
private $iLastUpstreamId;
|
||||||
// This defines each share
|
// This defines each share
|
||||||
public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time, $difficulty;
|
public $rem_host, $username, $our_result, $upstream_result, $reason, $solution, $time, $difficulty;
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $user, $block, $config) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->user = $user;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->block = $block;
|
|
||||||
$this->debug->append("Instantiated Share class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and set methods
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch archive tables name for this class
|
* Fetch archive tables name for this class
|
||||||
* @param none
|
* @param none
|
||||||
@ -38,13 +20,43 @@ class Share {
|
|||||||
public function getArchiveTableName() {
|
public function getArchiveTableName() {
|
||||||
return $this->tableArchive;
|
return $this->tableArchive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch normal table name for this class
|
* Fetch a single share by ID
|
||||||
* @param none
|
* @param id int Share ID
|
||||||
* @return data string Table name
|
* @return array Share data
|
||||||
**/
|
**/
|
||||||
public function getTableName() {
|
public function getShareById($id) {
|
||||||
return $this->table;
|
return $this->getAllAssoc($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an entire shares data
|
||||||
|
**/
|
||||||
|
public function updateShareById($id, $data) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$sql = "UPDATE $this->table SET";
|
||||||
|
$start = true;
|
||||||
|
// Remove ID column
|
||||||
|
unset($data['id']);
|
||||||
|
foreach ($data as $column => $value) {
|
||||||
|
$start == true ? $sql .= " $column = ? " : $sql .= ", $column = ?";
|
||||||
|
$start = false;
|
||||||
|
switch($column) {
|
||||||
|
case 'difficulty':
|
||||||
|
$this->addParam('d', $value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->addParam('s', $value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$sql .= " WHERE id = ? LIMIT 1";
|
||||||
|
$this->addParam('i', $id);
|
||||||
|
$stmt = $this->mysqli->prepare($sql);
|
||||||
|
if ($this->checkStmt($stmt) && call_user_func_array( array($stmt, 'bind_param'), $this->getParam()) && $stmt->execute())
|
||||||
|
return true;
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,14 +64,10 @@ class Share {
|
|||||||
* Used for PPS calculations without moving to archive
|
* Used for PPS calculations without moving to archive
|
||||||
**/
|
**/
|
||||||
public function getLastInsertedShareId() {
|
public function getLastInsertedShareId() {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->table");
|
||||||
SELECT MAX(id) AS id FROM $this->table
|
|
||||||
");
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->id;
|
return $result->fetch_object()->id;
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->setErrorMessage('Failed to fetch last inserted share ID');
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,14 +83,9 @@ class Share {
|
|||||||
WHERE our_result = 'Y'
|
WHERE our_result = 'Y'
|
||||||
AND id > ? AND id <= ?
|
AND id > ? AND id <= ?
|
||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
$stmt->bind_param('ii', $previous_upstream, $current_upstream);
|
|
||||||
$stmt->execute();
|
|
||||||
$result = $stmt->get_result();
|
|
||||||
$stmt->close();
|
|
||||||
return $result->fetch_object()->total;
|
return $result->fetch_object()->total;
|
||||||
}
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,7 +111,7 @@ class Share {
|
|||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,19 +121,17 @@ class Share {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->table");
|
$stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->table");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->id;
|
return $result->fetch_object()->id;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the highest available share ID from archive
|
* Fetch the highest available share ID from archive
|
||||||
**/
|
**/
|
||||||
function getMaxArchiveShareId() {
|
function getMaxArchiveShareId() {
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->tableArchive");
|
||||||
SELECT MAX(share_id) AS share_id FROM $this->tableArchive
|
|
||||||
");
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->share_id;
|
return $result->fetch_object()->share_id;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -161,7 +162,7 @@ class Share {
|
|||||||
}
|
}
|
||||||
if (is_array($aData)) return $aData;
|
if (is_array($aData)) return $aData;
|
||||||
}
|
}
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,8 +186,7 @@ class Share {
|
|||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,20 +202,22 @@ class Share {
|
|||||||
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
|
SELECT id, username, our_result, upstream_result, ?, time, IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
|
||||||
FROM $this->table
|
FROM $this->table
|
||||||
WHERE id > ? AND id <= ?");
|
WHERE id > ? AND id <= ?");
|
||||||
if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute()) {
|
if ($this->checkStmt($archive_stmt) && $archive_stmt->bind_param('iii', $block_id, $previous_upstream, $current_upstream) && $archive_stmt->execute())
|
||||||
$archive_stmt->close();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
return $this->sqlError();
|
||||||
// Catchall
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete accounted shares from shares table
|
||||||
|
* @param current_upstream int Current highest upstream ID
|
||||||
|
* @param previous_upstream int Previous upstream ID
|
||||||
|
* @return bool true or false
|
||||||
|
**/
|
||||||
public function deleteAccountedShares($current_upstream, $previous_upstream=0) {
|
public function deleteAccountedShares($current_upstream, $previous_upstream=0) {
|
||||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ?");
|
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE id > ? AND id <= ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $previous_upstream, $current_upstream) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Set/get last found share accepted by upstream: id and accounts
|
* Set/get last found share accepted by upstream: id and accounts
|
||||||
@ -229,7 +231,10 @@ class Share {
|
|||||||
public function getUpstreamFinder() {
|
public function getUpstreamFinder() {
|
||||||
return @$this->oUpstream->account;
|
return @$this->oUpstream->account;
|
||||||
}
|
}
|
||||||
public function getUpstreamId() {
|
public function getUpstreamWorker() {
|
||||||
|
return @$this->oUpstream->worker;
|
||||||
|
}
|
||||||
|
public function getUpstreamShareId() {
|
||||||
return @$this->oUpstream->id;
|
return @$this->oUpstream->id;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -240,7 +245,7 @@ class Share {
|
|||||||
* @param last int Skips all shares up to last to find new share
|
* @param last int Skips all shares up to last to find new share
|
||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function setUpstream($aBlock, $last=0) {
|
public function findUpstreamShare($aBlock, $last=0) {
|
||||||
// Many use stratum, so we create our stratum check first
|
// Many use stratum, so we create our stratum check first
|
||||||
$version = pack("I*", sprintf('%08d', $aBlock['version']));
|
$version = pack("I*", sprintf('%08d', $aBlock['version']));
|
||||||
$previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash']));
|
$previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash']));
|
||||||
@ -252,39 +257,39 @@ class Share {
|
|||||||
$header_hex = implode(unpack("H*", $header_bin));
|
$header_hex = implode(unpack("H*", $header_bin));
|
||||||
|
|
||||||
// Stratum supported blockhash solution entry
|
// Stratum supported blockhash solution entry
|
||||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $aBlock['hash']) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $aBlock['hash']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$this->oUpstream = $result->fetch_object();
|
$this->oUpstream = $result->fetch_object();
|
||||||
$this->share_type = 'startum_blockhash';
|
$this->share_type = 'stratum_blockhash';
|
||||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stratum scrypt hash check
|
// Stratum scrypt hash check
|
||||||
$scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32)));
|
$scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32)));
|
||||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution = ? LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$this->oUpstream = $result->fetch_object();
|
$this->oUpstream = $result->fetch_object();
|
||||||
$this->share_type = 'startum_solution';
|
$this->share_type = 'stratum_solution';
|
||||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed to fetch via startum solution, try pushpoold
|
// Failed to fetch via startum solution, try pushpoold
|
||||||
// Fallback to pushpoold solution type
|
// Fallback to pushpoold solution type
|
||||||
$ppheader = sprintf('%08d', $aBlock['version']) . word_reverse($aBlock['previousblockhash']) . word_reverse($aBlock['merkleroot']) . dechex($aBlock['time']) . $aBlock['bits'] . dechex($aBlock['nonce']);
|
$ppheader = sprintf('%08d', $aBlock['version']) . word_reverse($aBlock['previousblockhash']) . word_reverse($aBlock['merkleroot']) . dechex($aBlock['time']) . $aBlock['bits'] . dechex($aBlock['nonce']);
|
||||||
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution LIKE CONCAT(?, '%') LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id FROM $this->table WHERE solution LIKE CONCAT(?, '%') LIMIT 1");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $ppheader) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $ppheader) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$this->oUpstream = $result->fetch_object();
|
$this->oUpstream = $result->fetch_object();
|
||||||
$this->share_type = 'pp_solution';
|
$this->share_type = 'pp_solution';
|
||||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still no match, try upstream result with timerange
|
// Still no match, try upstream result with timerange
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id
|
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id
|
||||||
FROM $this->table
|
FROM $this->table
|
||||||
WHERE upstream_result = 'Y'
|
WHERE upstream_result = 'Y'
|
||||||
AND id > ?
|
AND id > ?
|
||||||
@ -294,14 +299,14 @@ class Share {
|
|||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$this->oUpstream = $result->fetch_object();
|
$this->oUpstream = $result->fetch_object();
|
||||||
$this->share_type = 'upstream_share';
|
$this->share_type = 'upstream_share';
|
||||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We failed again, now we take ANY result matching the timestamp
|
// We failed again, now we take ANY result matching the timestamp
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id
|
SUBSTRING_INDEX( `username` , '.', 1 ) AS account, username as worker, id
|
||||||
FROM $this->table
|
FROM $this->table
|
||||||
WHERE our_result = 'Y'
|
WHERE our_result = 'Y'
|
||||||
AND id > ?
|
AND id > ?
|
||||||
@ -310,10 +315,10 @@ class Share {
|
|||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $aBlock['time']) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$this->oUpstream = $result->fetch_object();
|
$this->oUpstream = $result->fetch_object();
|
||||||
$this->share_type = 'any_share';
|
$this->share_type = 'any_share';
|
||||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
if (!empty($this->oUpstream->account) && !empty($this->oUpstream->worker) && is_int($this->oUpstream->id))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Catchall
|
$this->setErrorMessage($this->getErrorMsg('E0052', $aBlock['height']));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,21 +337,22 @@ class Share {
|
|||||||
AND id <= ? AND @total < ?
|
AND id <= ? AND @total < ?
|
||||||
ORDER BY id DESC
|
ORDER BY id DESC
|
||||||
) AS b
|
) AS b
|
||||||
WHERE total <= ?
|
WHERE total <= ?");
|
||||||
");
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $current_upstream, $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $current_upstream, $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->id;
|
return $result->fetch_object()->id;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the lowest needed share ID from archive
|
* Fetch the lowest needed share ID from archive
|
||||||
**/
|
**/
|
||||||
function getMinArchiveShareId($iCount) {
|
function getMinArchiveShareId($iCount) {
|
||||||
|
// We don't use baseline here to be more accurate
|
||||||
|
$iCount = $iCount * pow(2, ($this->config['difficulty'] - 16));
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT MIN(b.share_id) AS share_id FROM
|
SELECT MIN(b.share_id) AS share_id FROM
|
||||||
(
|
(
|
||||||
SELECT share_id, @total := @total + (IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) / POW(2, (" . $this->config['difficulty'] . " - 16))) AS total
|
SELECT share_id, @total := @total + IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS total
|
||||||
FROM $this->tableArchive, (SELECT @total := 0) AS a
|
FROM $this->tableArchive, (SELECT @total := 0) AS a
|
||||||
WHERE our_result = 'Y'
|
WHERE our_result = 'Y'
|
||||||
AND @total < ?
|
AND @total < ?
|
||||||
@ -356,20 +362,14 @@ class Share {
|
|||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iCount, $iCount) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->share_id;
|
return $result->fetch_object()->share_id;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function
|
|
||||||
**/
|
|
||||||
private function checkStmt($bState) {
|
|
||||||
if ($bState ===! true) {
|
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$share = new Share($debug, $mysqli, $user, $block, $config);
|
$share = new Share();
|
||||||
|
$share->setDebug($debug);
|
||||||
|
$share->setMysql($mysqli);
|
||||||
|
$share->setConfig($config);
|
||||||
|
$share->setUser($user);
|
||||||
|
$share->setBlock($block);
|
||||||
|
$share->setErrorCodes($aErrorCodes);
|
||||||
|
|||||||
@ -10,31 +10,10 @@ if (!defined('SECURITY'))
|
|||||||
* Statistics should be non-intrusive and not change any
|
* Statistics should be non-intrusive and not change any
|
||||||
* rows in our database to ensure data integrity for the backend
|
* rows in our database to ensure data integrity for the backend
|
||||||
**/
|
**/
|
||||||
class Statistics {
|
class Statistics extends Base {
|
||||||
private $sError = '';
|
protected $table = 'statistics_shares';
|
||||||
private $table = 'statistics_shares';
|
|
||||||
private $getcache = true;
|
private $getcache = true;
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $config, $share, $user, $block, $memcache) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->share = $share;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->user = $user;
|
|
||||||
$this->block = $block;
|
|
||||||
$this->memcache = $memcache;
|
|
||||||
$this->debug->append("Instantiated Share class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some basic get and set methods
|
|
||||||
**/
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable fetching values from cache
|
// Disable fetching values from cache
|
||||||
public function setGetCache($set=false) {
|
public function setGetCache($set=false) {
|
||||||
$this->getcache = $set;
|
$this->getcache = $set;
|
||||||
@ -43,13 +22,74 @@ class Statistics {
|
|||||||
return $this->getcache;
|
return $this->getcache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkStmt($bState) {
|
/**
|
||||||
if ($bState ===! true) {
|
* Get our first block found
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
*
|
||||||
$this->setErrorMessage('Failed to prepare statement');
|
**/
|
||||||
return false;
|
public function getFirstBlockFound() {
|
||||||
}
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
return true;
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT IFNULL(MIN(time), 0) AS time FROM " . $this->block->getTableName());
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->time;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch last found blocks by time
|
||||||
|
**/
|
||||||
|
function getLastBlocksbyTime() {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
COUNT(id) AS Total,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0, 1, 0)), 0) AS TotalValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1, 1, 0)), 0) AS TotalOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0, difficulty, 0)), 0) AS TotalDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1, shares, 0))), 0) AS TotalShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1, POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS TotalEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1, amount, 0)), 0) AS TotalAmount,
|
||||||
|
IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourTotal,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), 1, 0)), 0) AS 1HourOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), difficulty, 0)), 0) AS 1HourDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), shares, 0))), 0) AS 1HourShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS 1HourEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 3600 SECOND), amount, 0)), 0) AS 1HourAmount,
|
||||||
|
IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourTotal,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), 1, 0)), 0) AS 24HourOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), difficulty, 0)), 0) AS 24HourDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), shares, 0))), 0) AS 24HourShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS 24HourEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 86400 SECOND), amount, 0)), 0) AS 24HourAmount,
|
||||||
|
IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysTotal,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), 1, 0)), 0) AS 7DaysOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), difficulty, 0)), 0) AS 7DaysDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), shares, 0))), 0) AS 7DaysShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS 7DaysEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 604800 SECOND), amount, 0)), 0) AS 7DaysAmount,
|
||||||
|
IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksTotal,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), 1, 0)), 0) AS 4WeeksOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), difficulty, 0)), 0) AS 4WeeksDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), shares, 0))), 0) AS 4WeeksShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS 4WeeksEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 2419200 SECOND), amount, 0)), 0) AS 4WeeksAmount,
|
||||||
|
IFNULL(SUM(IF(FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthTotal,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthValid,
|
||||||
|
IFNULL(SUM(IF(confirmations = -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), 1, 0)), 0) AS 12MonthOrphan,
|
||||||
|
IFNULL(SUM(IF(confirmations > 0 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), difficulty, 0)), 0) AS 12MonthDifficulty,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), shares, 0))), 0) AS 12MonthShares,
|
||||||
|
IFNULL(ROUND(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty / POW(2, (" . $this->config['difficulty'] . " -16)), 0))), 0) AS 12MonthEstimatedShares,
|
||||||
|
IFNULL(SUM(IF(confirmations > -1 AND FROM_UNIXTIME(time) >= DATE_SUB(now(), INTERVAL 29030400 SECOND), amount, 0)), 0) AS 12MonthAmount
|
||||||
|
FROM " . $this->block->getTableName());
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $this->memcache->setCache(__FUNCTION__, $result->fetch_assoc());
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,18 +105,88 @@ class Statistics {
|
|||||||
b.*,
|
b.*,
|
||||||
a.username AS finder,
|
a.username AS finder,
|
||||||
a.is_anonymous AS is_anonymous,
|
a.is_anonymous AS is_anonymous,
|
||||||
ROUND((difficulty * 65535) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares
|
ROUND((difficulty * POW(2, 32 - " . $this->config['target_bits'] . ")) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares
|
||||||
FROM " . $this->block->getTableName() . " AS b
|
FROM " . $this->block->getTableName() . " AS b
|
||||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||||
ON b.account_id = a.id
|
ON b.account_id = a.id
|
||||||
ORDER BY height DESC LIMIT ?");
|
ORDER BY height DESC LIMIT ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
|
return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to find blocks:" . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get our last $limit blocks found by height
|
||||||
|
* @param limit int Last limit blocks
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
public function getBlocksFoundHeight($iHeight=0, $limit=10) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__ . $iHeight . $limit)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
b.*,
|
||||||
|
a.username AS finder,
|
||||||
|
a.is_anonymous AS is_anonymous,
|
||||||
|
ROUND((difficulty * POW(2, 32 - " . $this->config['target_bits'] . ")) / POW(2, (" . $this->config['difficulty'] . " -16)), 0) AS estshares
|
||||||
|
FROM " . $this->block->getTableName() . " AS b
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||||
|
ON b.account_id = a.id
|
||||||
|
WHERE b.height <= ?
|
||||||
|
ORDER BY height DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $iHeight, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $iHeight . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SUM of blocks found and generated Coins for each Account
|
||||||
|
* @param limit int Last limit blocks
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
public function getBlocksSolvedbyAccount($limit=25) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__ . $limit)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
b.*,
|
||||||
|
a.username AS finder,
|
||||||
|
a.is_anonymous AS is_anonymous,
|
||||||
|
COUNT(b.id) AS solvedblocks,
|
||||||
|
SUM(b.amount) AS generatedcoins
|
||||||
|
FROM " . $this->block->getTableName() . " AS b
|
||||||
|
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||||
|
ON b.account_id = a.id
|
||||||
|
WHERE confirmations > 0
|
||||||
|
GROUP BY finder
|
||||||
|
ORDER BY solvedblocks DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SUM of blocks found and generated Coins for each worker
|
||||||
|
* @param limit int Last limit blocks
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
public function getBlocksSolvedbyWorker($account_id, $limit=25) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__ . $account_id . $limit)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
worker_name AS finder,
|
||||||
|
COUNT(id) AS solvedblocks,
|
||||||
|
SUM(amount) AS generatedcoins
|
||||||
|
FROM " . $this->block->getTableName() . "
|
||||||
|
WHERE account_id = ? AND worker_name != 'unknown'
|
||||||
|
GROUP BY finder
|
||||||
|
ORDER BY solvedblocks DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $account_id . $limit, $result->fetch_all(MYSQLI_ASSOC), 5);
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently the only function writing to the database
|
* Currently the only function writing to the database
|
||||||
* Stored per block user statistics of valid and invalid shares
|
* Stored per block user statistics of valid and invalid shares
|
||||||
@ -88,9 +198,41 @@ class Statistics {
|
|||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, block_id) VALUES (?, ?, ?, ?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, block_id) VALUES (?, ?, ?, ?)");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true;
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true;
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to update share stats: " . $this->mysqli->error);
|
}
|
||||||
return false;
|
|
||||||
|
/**
|
||||||
|
* update user statistics of valid and invalid pplns shares
|
||||||
|
**/
|
||||||
|
public function updatePPLNSShareStatistics($aStats, $iBlockId) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
UPDATE $this->table SET pplns_valid = ?, pplns_invalid = ? WHERE account_id = ? AND block_id = ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['valid'], $aStats['invalid'], $aStats['id'], $iBlockId) && $stmt->execute()) return true;
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert user statistics of valid and invalid pplns shares "rbpplns"
|
||||||
|
**/
|
||||||
|
public function insertPPLNSShareStatistics($aStats, $iBlockId) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, valid, invalid, pplns_valid, pplns_invalid, block_id) VALUES (?, 0, 0, ?, ?, ?)");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $aStats['id'], $aStats['valid'], $aStats['invalid'], $iBlockId) && $stmt->execute()) return true;
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the share ID from stats for rbpplns
|
||||||
|
**/
|
||||||
|
function getIdShareStatistics($aStats, $iBlockId) {
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT id AS id FROM $this->table
|
||||||
|
WHERE account_id = ? AND block_id = ?
|
||||||
|
");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aStats['id'], $iBlockId) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_object()->id;
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,20 +248,20 @@ class Statistics {
|
|||||||
SELECT
|
SELECT
|
||||||
(
|
(
|
||||||
(
|
(
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0) AS hashrate
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND our_result = 'Y'
|
||||||
) + (
|
) + (
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0) AS hashrate
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND our_result = 'Y'
|
||||||
)
|
)
|
||||||
) AS hashrate
|
) AS hashrate
|
||||||
FROM DUAL");
|
FROM DUAL");
|
||||||
// Catchall
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate);
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate);
|
||||||
$this->debug->append("Failed to get hashrate: " . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,17 +279,17 @@ class Statistics {
|
|||||||
SELECT ROUND(COUNT(id) / ?, 2) AS sharerate
|
SELECT ROUND(COUNT(id) / ?, 2) AS sharerate
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND our_result = 'Y'
|
||||||
) + (
|
) + (
|
||||||
SELECT ROUND(COUNT(id) / ?, 2) AS sharerate
|
SELECT ROUND(COUNT(id) / ?, 2) AS sharerate
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
WHERE time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND our_result = 'Y'
|
||||||
)
|
)
|
||||||
) AS sharerate
|
) AS sharerate
|
||||||
FROM DUAL");
|
FROM DUAL");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate);
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiii', $interval, $interval, $interval, $interval) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate);
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch share rate: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,9 +321,7 @@ class Statistics {
|
|||||||
WHERE UNIX_TIMESTAMP(time) > IFNULL((SELECT MAX(time) FROM " . $this->block->getTableName() . "), 0)");
|
WHERE UNIX_TIMESTAMP(time) > IFNULL((SELECT MAX(time) FROM " . $this->block->getTableName() . "), 0)");
|
||||||
if ( $this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() )
|
if ( $this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
return $this->memcache->setCache(STATISTICS_ROUND_SHARES, $result->fetch_assoc());
|
return $this->memcache->setCache(STATISTICS_ROUND_SHARES, $result->fetch_assoc());
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch round shares: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -229,9 +369,7 @@ class Statistics {
|
|||||||
$data['share_id'] = $this->share->getMaxShareId();
|
$data['share_id'] = $this->share->getMaxShareId();
|
||||||
return $this->memcache->setCache(STATISTICS_ALL_USER_SHARES, $data);
|
return $this->memcache->setCache(STATISTICS_ALL_USER_SHARES, $data);
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Unable to fetch all users round shares: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,18 +399,15 @@ class Statistics {
|
|||||||
AND u.id = ?");
|
AND u.id = ?");
|
||||||
if ($stmt && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc());
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc());
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Unable to fetch user round shares: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Admin panel specific query
|
* Admin panel specific query
|
||||||
* @return data array invlid and valid shares for all accounts
|
* @return data array User settings and shares
|
||||||
**/
|
**/
|
||||||
public function getAllUserStats($filter='%') {
|
public function getAllUserStats($filter='%') {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $filter)) return $data;
|
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
a.id AS id,
|
a.id AS id,
|
||||||
@ -281,22 +416,25 @@ class Statistics {
|
|||||||
a.no_fees as no_fees,
|
a.no_fees as no_fees,
|
||||||
a.username AS username,
|
a.username AS username,
|
||||||
a.donate_percent AS donate_percent,
|
a.donate_percent AS donate_percent,
|
||||||
a.email AS email,
|
a.email AS email
|
||||||
ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS shares
|
|
||||||
FROM " . $this->user->getTableName() . " AS a
|
FROM " . $this->user->getTableName() . " AS a
|
||||||
LEFT JOIN " . $this->share->getTableName() . " AS s
|
|
||||||
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
|
||||||
WHERE
|
WHERE
|
||||||
a.username LIKE ?
|
a.username LIKE ?
|
||||||
GROUP BY username
|
GROUP BY username
|
||||||
ORDER BY username");
|
ORDER BY username");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $filter) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $filter) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $filter, $result->fetch_all(MYSQLI_ASSOC));
|
// Add our cached shares to the users
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$row['shares'] = $this->getUserShares($row['id']);
|
||||||
|
$aUsers[] = $row;
|
||||||
|
}
|
||||||
|
return $aUsers;
|
||||||
}
|
}
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as getUserShares for Hashrate
|
* Fetch total user hashrate based on shares and archived shares
|
||||||
* @param account_id integer User ID
|
* @param account_id integer User ID
|
||||||
* @return data integer Current Hashrate in khash/s
|
* @return data integer Current Hashrate in khash/s
|
||||||
**/
|
**/
|
||||||
@ -305,27 +443,71 @@ class Statistics {
|
|||||||
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
(
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
|
FROM (
|
||||||
FROM " . $this->share->getTableName() . " AS s,
|
SELECT
|
||||||
" . $this->user->getTableName() . " AS u
|
s.id, s.our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty) AS difficulty
|
||||||
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
FROM
|
||||||
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
shares AS s,
|
||||||
AND u.id = ?
|
accounts AS u
|
||||||
) + (
|
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / ? / 1000), 0) AS hashrate
|
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
FROM " . $this->share->getArchiveTableName() . " AS s,
|
AND s.our_result = 'Y'
|
||||||
" . $this->user->getTableName() . " AS u
|
AND u.id = ?
|
||||||
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
UNION
|
||||||
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
SELECT
|
||||||
AND u.id = ?
|
s.share_id, s.our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty) AS difficulty
|
||||||
) AS hashrate
|
FROM
|
||||||
FROM DUAL");
|
shares_archive AS s,
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiiii", $interval, $interval, $account_id, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
accounts AS u
|
||||||
|
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
|
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND s.our_result = 'Y'
|
||||||
|
AND u.id = ?
|
||||||
|
) AS temp");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $interval, $interval, $account_id, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate);
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate);
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch hashrate: " . $this->mysqli->error);
|
}
|
||||||
return false;
|
|
||||||
|
public function getUserUnpaidPPSShares($account_id, $last_paid_pps_id) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS total
|
||||||
|
FROM " . $this->share->getTableName() . " AS s
|
||||||
|
JOIN " . $this->user->getTableName() . " AS a
|
||||||
|
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
|
AND a.id = ?
|
||||||
|
AND s.id > ?
|
||||||
|
WHERE our_result = 'Y'");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $last_paid_pps_id) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->total);
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get average share difficulty across all workers for user
|
||||||
|
* @param account_id int Account ID
|
||||||
|
* @param interval int Data interval in seconds
|
||||||
|
* @return double Share difficulty or 0
|
||||||
|
**/
|
||||||
|
public function getUserShareDifficulty($account_id, $interval=600) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff,
|
||||||
|
COUNT(s.id) AS total
|
||||||
|
FROM " . $this->share->getTableName() . " AS s JOIN " . $this->user->getTableName() . " AS a
|
||||||
|
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
|
WHERE s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND our_result = 'Y'
|
||||||
|
AND a.id = ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->avgsharediff);
|
||||||
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -338,29 +520,31 @@ class Statistics {
|
|||||||
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
(
|
IFNULL(COUNT(*) / ?, 0) AS sharerate
|
||||||
(
|
FROM (
|
||||||
SELECT COUNT(s.id) / ? AS sharerate
|
SELECT
|
||||||
FROM " . $this->share->getTableName() . " AS s,
|
s.id
|
||||||
" . $this->user->getTableName() . " AS u
|
FROM
|
||||||
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
shares AS s,
|
||||||
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
accounts AS u
|
||||||
AND u.id = ?
|
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
) + (
|
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
SELECT COUNT(s.id) / ? AS sharerate
|
AND s.our_result = 'Y'
|
||||||
FROM " . $this->share->getArchiveTableName() . " AS s,
|
AND u.id = ?
|
||||||
" . $this->user->getTableName() . " AS u
|
UNION
|
||||||
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
SELECT
|
||||||
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
s.share_id
|
||||||
AND u.id = ?
|
FROM
|
||||||
)
|
shares_archive AS s,
|
||||||
) AS sharerate
|
accounts AS u
|
||||||
FROM DUAL");
|
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiiii", $interval, $interval, $account_id, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
AND s.our_result = 'Y'
|
||||||
|
AND u.id = ?
|
||||||
|
) AS temp");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $interval, $interval, $account_id, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->sharerate);
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->sharerate);
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch sharerate: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -372,17 +556,16 @@ class Statistics {
|
|||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if ($data = $this->memcache->get(__FUNCTION__ . $worker_id)) return $data;
|
if ($data = $this->memcache->get(__FUNCTION__ . $worker_id)) return $data;
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536 / 600 / 1000), 0) AS hashrate
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000), 0) AS hashrate
|
||||||
FROM " . $this->share->getTableName() . " AS s,
|
FROM " . $this->share->getTableName() . " AS s,
|
||||||
" . $this->user->getTableName() . " AS u
|
" . $this->user->getTableName() . " AS u
|
||||||
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
|
AND our_result = 'Y'
|
||||||
AND s.time > DATE_SUB(now(), INTERVAL 600 SECOND)
|
AND s.time > DATE_SUB(now(), INTERVAL 600 SECOND)
|
||||||
AND u.id = ?");
|
AND u.id = ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() )
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $worker_id, $result->fetch_object()->hashrate);
|
return $this->memcache->setCache(__FUNCTION__ . $worker_id, $result->fetch_object()->hashrate);
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch hashrate: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -397,28 +580,32 @@ class Statistics {
|
|||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'shares':
|
case 'shares':
|
||||||
if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) {
|
if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) {
|
||||||
// Use global cache to build data
|
// Use global cache to build data, if we have any data there
|
||||||
$max = 0;
|
if (!empty($data['data']) && is_array($data['data'])) {
|
||||||
foreach($data['data'] as $key => $aUser) {
|
foreach($data['data'] as $key => $aUser) {
|
||||||
$shares[$key] = $aUser['valid'];
|
$shares[$key] = $aUser['valid'];
|
||||||
$username[$key] = $aUser['username'];
|
$username[$key] = $aUser['username'];
|
||||||
|
}
|
||||||
|
array_multisort($shares, SORT_DESC, $username, SORT_ASC, $data['data']);
|
||||||
|
$count = 0;
|
||||||
|
foreach ($data['data'] as $key => $aUser) {
|
||||||
|
if ($count == $limit) break;
|
||||||
|
$count++;
|
||||||
|
$data_new[$key]['shares'] = $aUser['valid'];
|
||||||
|
$data_new[$key]['account'] = $aUser['username'];
|
||||||
|
$data_new[$key]['donate_percent'] = $aUser['donate_percent'];
|
||||||
|
$data_new[$key]['is_anonymous'] = $aUser['is_anonymous'];
|
||||||
|
}
|
||||||
|
return $data_new;
|
||||||
}
|
}
|
||||||
array_multisort($shares, SORT_DESC, $username, SORT_ASC, $data['data']);
|
|
||||||
foreach ($data['data'] as $key => $aUser) {
|
|
||||||
$data_new[$key]['shares'] = $aUser['valid'];
|
|
||||||
$data_new[$key]['account'] = $aUser['username'];
|
|
||||||
$data_new[$key]['donate_percent'] = $aUser['donate_percent'];
|
|
||||||
$data_new[$key]['is_anonymous'] = $aUser['is_anonymous'];
|
|
||||||
}
|
|
||||||
return $data_new;
|
|
||||||
}
|
}
|
||||||
// No cached data, fallback to SQL and cache in local cache
|
// No cached data, fallback to SQL and cache in local cache
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
|
a.username AS account,
|
||||||
a.donate_percent AS donate_percent,
|
a.donate_percent AS donate_percent,
|
||||||
a.is_anonymous AS is_anonymous,
|
a.is_anonymous AS is_anonymous,
|
||||||
ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS shares,
|
ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS shares
|
||||||
SUBSTRING_INDEX( s.username, '.', 1 ) AS account
|
|
||||||
FROM " . $this->share->getTableName() . " AS s
|
FROM " . $this->share->getTableName() . " AS s
|
||||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||||
ON SUBSTRING_INDEX( s.username, '.', 1 ) = a.username
|
ON SUBSTRING_INDEX( s.username, '.', 1 ) = a.username
|
||||||
@ -428,22 +615,21 @@ class Statistics {
|
|||||||
LIMIT ?");
|
LIMIT ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC));
|
return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC));
|
||||||
$this->debug->append("Fetching shares failed: ");
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'hashes':
|
case 'hashes':
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
|
a.username AS account,
|
||||||
a.donate_percent AS donate_percent,
|
a.donate_percent AS donate_percent,
|
||||||
a.is_anonymous AS is_anonymous,
|
a.is_anonymous AS is_anonymous,
|
||||||
IFNULL(ROUND(SUM(t1.difficulty) * 65536/600/1000, 2), 0) AS hashrate,
|
IFNULL(ROUND(SUM(t1.difficulty) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000, 2), 0) AS hashrate
|
||||||
SUBSTRING_INDEX( t1.username, '.', 1 ) AS account
|
|
||||||
FROM
|
FROM
|
||||||
(
|
(
|
||||||
SELECT IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
SELECT id, IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
||||||
UNION ALL
|
UNION
|
||||||
SELECT IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getArchiveTableName() ." WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
SELECT share_id, IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty, username FROM " . $this->share->getArchiveTableName() ." WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) AND our_result = 'Y'
|
||||||
) AS t1
|
) AS t1
|
||||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||||
ON SUBSTRING_INDEX( t1.username, '.', 1 ) = a.username
|
ON SUBSTRING_INDEX( t1.username, '.', 1 ) = a.username
|
||||||
@ -451,8 +637,7 @@ class Statistics {
|
|||||||
ORDER BY hashrate DESC LIMIT ?");
|
ORDER BY hashrate DESC LIMIT ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC));
|
return $this->memcache->setCache(__FUNCTION__ . $type . $limit, $result->fetch_all(MYSQLI_ASSOC));
|
||||||
$this->debug->append("Fetching shares failed: " . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -467,20 +652,24 @@ class Statistics {
|
|||||||
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * 65536/3600/1000), 0) AS hashrate,
|
a.id,
|
||||||
|
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||||
HOUR(s.time) AS hour
|
HOUR(s.time) AS hour
|
||||||
FROM " . $this->share->getTableName() . " AS s, accounts AS a
|
FROM " . $this->share->getTableName() . " AS s, accounts AS a
|
||||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||||
|
AND our_result = 'Y'
|
||||||
AND time > NOW() - INTERVAL 25 HOUR
|
AND time > NOW() - INTERVAL 25 HOUR
|
||||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
AND a.id = ?
|
AND a.id = ?
|
||||||
GROUP BY HOUR(time)
|
GROUP BY HOUR(time)
|
||||||
UNION ALL
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * 65536/3600/1000), 0) AS hashrate,
|
share_id,
|
||||||
|
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||||
HOUR(s.time) AS hour
|
HOUR(s.time) AS hour
|
||||||
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a
|
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a
|
||||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||||
|
AND our_result = 'Y'
|
||||||
AND time > NOW() - INTERVAL 25 HOUR
|
AND time > NOW() - INTERVAL 25 HOUR
|
||||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||||
AND a.id = ?
|
AND a.id = ?
|
||||||
@ -493,9 +682,7 @@ class Statistics {
|
|||||||
while ($row = $result->fetch_assoc()) $aData[$row['hour']] = $row['hashrate'];
|
while ($row = $result->fetch_assoc()) $aData[$row['hour']] = $row['hashrate'];
|
||||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData);
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData);
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -508,19 +695,23 @@ class Statistics {
|
|||||||
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
|
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * 65536/3600/1000), 0) AS hashrate,
|
id,
|
||||||
|
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||||
HOUR(s.time) AS hour
|
HOUR(s.time) AS hour
|
||||||
FROM " . $this->share->getTableName() . " AS s
|
FROM " . $this->share->getTableName() . " AS s
|
||||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||||
AND time > NOW() - INTERVAL 25 HOUR
|
AND time > NOW() - INTERVAL 25 HOUR
|
||||||
|
AND our_result = 'Y'
|
||||||
GROUP BY HOUR(time)
|
GROUP BY HOUR(time)
|
||||||
UNION ALL
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * 65536/3600/1000), 0) AS hashrate,
|
share_id,
|
||||||
|
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
|
||||||
HOUR(s.time) AS hour
|
HOUR(s.time) AS hour
|
||||||
FROM " . $this->share->getArchiveTableName() . " AS s
|
FROM " . $this->share->getArchiveTableName() . " AS s
|
||||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||||
AND time > NOW() - INTERVAL 25 HOUR
|
AND time > NOW() - INTERVAL 25 HOUR
|
||||||
|
AND our_result = 'Y'
|
||||||
GROUP BY HOUR(time)");
|
GROUP BY HOUR(time)");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) {
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
$iStartHour = date('G');
|
$iStartHour = date('G');
|
||||||
@ -530,35 +721,95 @@ class Statistics {
|
|||||||
while ($row = $result->fetch_assoc()) $aData[$row['hour']] = (int) $row['hashrate'];
|
while ($row = $result->fetch_assoc()) $aData[$row['hour']] = (int) $row['hashrate'];
|
||||||
return $this->memcache->setCache(__FUNCTION__, $aData);
|
return $this->memcache->setCache(__FUNCTION__, $aData);
|
||||||
}
|
}
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get user estimated payouts based on share counts
|
* get user estimated payouts based on share counts
|
||||||
* @param aRoundShares array Round shares
|
* @param value1 mixed Round shares OR share rate
|
||||||
* @param aUserShares array User shares
|
* @param value2 mixed User shares OR share difficulty
|
||||||
* @param dDonate double User donation setting
|
* @param dDonate double User donation setting
|
||||||
* @param bNoFees bool User no-fees option setting
|
* @param bNoFees bool User no-fees option setting
|
||||||
* @return aEstimates array User estimations
|
* @return aEstimates array User estimations
|
||||||
**/
|
**/
|
||||||
public function getUserEstimates($aRoundShares, $aUserShares, $dDonate, $bNoFees) {
|
public function getUserEstimates($value1, $value2, $dDonate, $bNoFees, $ppsvalue=0) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
// Fetch some user information that we need
|
if ($this->config['payout_system'] != 'pps') {
|
||||||
if (@$aRoundShares['valid'] > 0 && @$aUserShares['valid'] > 0) {
|
if (@$value1['valid'] > 0 && @$value2['valid'] > 0) {
|
||||||
$aEstimates['block'] = round(( (int)$aUserShares['valid'] / (int)$aRoundShares['valid'] ) * (float)$this->config['reward'], 8);
|
$aEstimates['block'] = round(( (int)$value2['valid'] / (int)$value1['valid'] ) * (float)$this->config['reward'], 8);
|
||||||
$bNoFees == 0 ? $aEstimates['fee'] = round(((float)$this->config['fees'] / 100) * (float)$aEstimates['block'], 8) : $aEstimates['fee'] = 0;
|
$bNoFees == 0 ? $aEstimates['fee'] = round(((float)$this->config['fees'] / 100) * (float)$aEstimates['block'], 8) : $aEstimates['fee'] = 0;
|
||||||
$aEstimates['donation'] = round((( (float)$dDonate / 100) * ((float)$aEstimates['block'] - (float)$aEstimates['fee'])), 8);
|
$aEstimates['donation'] = round((( (float)$dDonate / 100) * ((float)$aEstimates['block'] - (float)$aEstimates['fee'])), 8);
|
||||||
$aEstimates['payout'] = round((float)$aEstimates['block'] - (float)$aEstimates['donation'] - (float)$aEstimates['fee'], 8);
|
$aEstimates['payout'] = round((float)$aEstimates['block'] - (float)$aEstimates['donation'] - (float)$aEstimates['fee'], 8);
|
||||||
|
} else {
|
||||||
|
$aEstimates['block'] = 0;
|
||||||
|
$aEstimates['fee'] = 0;
|
||||||
|
$aEstimates['donation'] = 0;
|
||||||
|
$aEstimates['payout'] = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$aEstimates['block'] = 0;
|
// Hack so we can use this method for PPS estimates too
|
||||||
$aEstimates['fee'] = 0;
|
// value1 = shares/s
|
||||||
$aEstimates['donation'] = 0;
|
// value2 = avg share difficulty
|
||||||
$aEstimates['payout'] = 0;
|
if (@$value1 > 0 && @$value2 > 0) {
|
||||||
|
$hour = 60 * 60;
|
||||||
|
$pps = $value1 * $value2 * $ppsvalue;
|
||||||
|
$aEstimates['hours1'] = $pps * $hour;
|
||||||
|
$aEstimates['hours24'] = $pps * 24 * $hour;
|
||||||
|
$aEstimates['days7'] = $pps * 24 * 7 * $hour;
|
||||||
|
$aEstimates['days14'] = $pps * 14 * 24 * $hour;
|
||||||
|
$aEstimates['days30'] = $pps * 30 * 24 * $hour;
|
||||||
|
} else {
|
||||||
|
$aEstimates['hours1'] = 0;
|
||||||
|
$aEstimates['hours24'] = 0;
|
||||||
|
$aEstimates['days7'] = 0;
|
||||||
|
$aEstimates['days14'] = 0;
|
||||||
|
$aEstimates['days30'] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return $aEstimates;
|
return $aEstimates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pool stats last 24 hours
|
||||||
|
* @param limit int Last number of hours
|
||||||
|
* @return array
|
||||||
|
**/
|
||||||
|
public function getPoolStatsHours($hour=24) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
if ($data = $this->memcache->get(__FUNCTION__ . $hour)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
IFNULL(COUNT(id), 0) as count,
|
||||||
|
IFNULL(AVG(difficulty), 0) as average,
|
||||||
|
IFNULL(ROUND(SUM((POW(2, ( 32 - " . $this->config['target_bits'] . " )) * difficulty) / POW(2, (" . $this->config['difficulty'] . " -16))), 0), 0) AS expected,
|
||||||
|
IFNULL(ROUND(SUM(shares)), 0) as shares,
|
||||||
|
IFNULL(SUM(amount), 0) as rewards
|
||||||
|
FROM " . $this->block->getTableName() . "
|
||||||
|
WHERE FROM_UNIXTIME(time) > DATE_SUB(now(), INTERVAL ? HOUR)
|
||||||
|
AND confirmations >= 1");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $hour) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $hour, $result->fetch_assoc());
|
||||||
|
return $this->sqlError();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caclulate estimated shares based on network difficulty and pool difficulty
|
||||||
|
* @param dDiff double Network difficulty
|
||||||
|
* @return shares integer Share count
|
||||||
|
**/
|
||||||
|
public function getEstimatedShares($dDiff) {
|
||||||
|
return round((POW(2, (32 - $this->config['target_bits'])) * $dDiff) / pow(2, ($this->config['difficulty'] - 16)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$statistics = new Statistics($debug, $mysqli, $config, $share, $user, $block, $memcache);
|
$statistics = new Statistics();
|
||||||
|
$statistics->setDebug($debug);
|
||||||
|
$statistics->setMysql($mysqli);
|
||||||
|
$statistics->setShare($share);
|
||||||
|
$statistics->setUser($user);
|
||||||
|
$statistics->setBlock($block);
|
||||||
|
$statistics->setMemcache($memcache);
|
||||||
|
$statistics->setConfig($config);
|
||||||
|
$statistics->setErrorCodes($aErrorCodes);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
if (!defined('SECURITY')) die('Hacking attempt');
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
class Token Extends Base {
|
class Token Extends Base {
|
||||||
var $table = 'tokens';
|
protected $table = 'tokens';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a token from our table
|
* Fetch a token from our table
|
||||||
@ -15,7 +15,7 @@ class Token Extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE token = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE token = ? LIMIT 1");
|
||||||
if ($stmt && $stmt->bind_param('s', $strToken) && $stmt->execute() && $result = $stmt->get_result())
|
if ($stmt && $stmt->bind_param('s', $strToken) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,9 +36,7 @@ class Token Extends Base {
|
|||||||
");
|
");
|
||||||
if ($stmt && $stmt->bind_param('sii', $strToken, $iToken_id, $account_id) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('sii', $strToken, $iToken_id, $account_id) && $stmt->execute())
|
||||||
return $strToken;
|
return $strToken;
|
||||||
$this->setErrorMessage('Unable to create new token');
|
return $this->sqlError();
|
||||||
$this->debug->append('Failed to create new token in database: ' . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +48,7 @@ class Token Extends Base {
|
|||||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE token = ? LIMIT 1");
|
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE token = ? LIMIT 1");
|
||||||
if ($stmt && $stmt->bind_param('s', $token) && $stmt->execute())
|
if ($stmt && $stmt->bind_param('s', $token) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,3 +56,4 @@ $oToken = new Token();
|
|||||||
$oToken->setDebug($debug);
|
$oToken->setDebug($debug);
|
||||||
$oToken->setMysql($mysqli);
|
$oToken->setMysql($mysqli);
|
||||||
$oToken->setTokenType($tokentype);
|
$oToken->setTokenType($tokentype);
|
||||||
|
$oToken->setErrorCodes($aErrorCodes);
|
||||||
|
|||||||
@ -5,7 +5,8 @@ if (!defined('SECURITY'))
|
|||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class Token_Type Extends Base {
|
class Token_Type Extends Base {
|
||||||
var $table = 'token_types';
|
protected $table = 'token_types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return ID for specific token
|
* Return ID for specific token
|
||||||
* @param strName string Token Name
|
* @param strName string Token Name
|
||||||
@ -19,3 +20,4 @@ class Token_Type Extends Base {
|
|||||||
$tokentype = new Token_Type();
|
$tokentype = new Token_Type();
|
||||||
$tokentype->setDebug($debug);
|
$tokentype->setDebug($debug);
|
||||||
$tokentype->setMysql($mysqli);
|
$tokentype->setMysql($mysqli);
|
||||||
|
$tokentype->setErrorCodes($aErrorCodes);
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class Tools extends Base {
|
|||||||
* @param auth array Optional authentication data to be sent with
|
* @param auth array Optional authentication data to be sent with
|
||||||
* @return dec array JSON decoded PHP array
|
* @return dec array JSON decoded PHP array
|
||||||
**/
|
**/
|
||||||
private function getApi($url, $target, $auth=NULL) {
|
public function getApi($url, $target, $auth=NULL) {
|
||||||
static $ch = null;
|
static $ch = null;
|
||||||
static $ch = null;
|
static $ch = null;
|
||||||
if (is_null($ch)) {
|
if (is_null($ch)) {
|
||||||
@ -32,9 +32,15 @@ class Tools extends Base {
|
|||||||
|
|
||||||
// run the query
|
// run the query
|
||||||
$res = curl_exec($ch);
|
$res = curl_exec($ch);
|
||||||
if ($res === false) throw new Exception('Could not get reply: '.curl_error($ch));
|
if ($res === false) {
|
||||||
|
$this->setErrorMessage('Could not get reply: '.curl_error($ch));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$dec = json_decode($res, true);
|
$dec = json_decode($res, true);
|
||||||
if (!$dec) throw new Exception('Invalid data received, please make sure connection is working and requested API exists');
|
if (!$dec) {
|
||||||
|
$this->setErrorMessage('Invalid data received, please make sure connection is working and requested API exists');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return $dec;
|
return $dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ if (!defined('SECURITY'))
|
|||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class Transaction extends Base {
|
class Transaction extends Base {
|
||||||
private $sError = '', $table = 'transactions';
|
protected $table = 'transactions';
|
||||||
public $num_rows = 0, $insert_id = 0;
|
public $num_rows = 0, $insert_id = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,14 +18,13 @@ class Transaction extends Base {
|
|||||||
* @param coin_address string Coin address for this transaction [optional]
|
* @param coin_address string Coin address for this transaction [optional]
|
||||||
* @return bool
|
* @return bool
|
||||||
**/
|
**/
|
||||||
public function addTransaction($account_id, $amount, $type='Credit', $block_id=NULL, $coin_address=NULL) {
|
public function addTransaction($account_id, $amount, $type='Credit', $block_id=NULL, $coin_address=NULL, $txid=NULL) {
|
||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, amount, block_id, type, coin_address) VALUES (?, ?, ?, ?, ?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, amount, block_id, type, coin_address, txid) VALUES (?, ?, ?, ?, ?, ?)");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("idiss", $account_id, $amount, $block_id, $type, $coin_address) && $stmt->execute()) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param("idisss", $account_id, $amount, $block_id, $type, $coin_address, $txid) && $stmt->execute()) {
|
||||||
$this->insert_id = $stmt->insert_id;
|
$this->insert_id = $stmt->insert_id;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$this->setErrorMessage("Failed to store transaction");
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -35,16 +34,20 @@ class Transaction extends Base {
|
|||||||
* @param bool boolean True or False
|
* @param bool boolean True or False
|
||||||
**/
|
**/
|
||||||
public function setArchived($account_id, $txid) {
|
public function setArchived($account_id, $txid) {
|
||||||
|
// Update all paid out transactions as archived
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
UPDATE $this->table AS t
|
UPDATE $this->table AS t
|
||||||
LEFT JOIN " . $this->block->getTableName() . " AS b
|
LEFT JOIN " . $this->block->getTableName() . " AS b
|
||||||
ON b.id = t.block_id
|
ON b.id = t.block_id
|
||||||
SET t.archived = 1
|
SET t.archived = 1
|
||||||
WHERE ( t.account_id = ? AND t.id <= ? AND b.confirmations >= ? )
|
WHERE t.archived = 0
|
||||||
OR ( t.account_id = ? AND t.id <= ? AND t.type IN ( 'Credit_PPS', 'Donation_PPS', 'Fee_PPS', 'TXFee', 'Debit_MP', 'Debit_AP' ) )");
|
AND (
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('iiiii', $account_id, $txid, $this->config['confirmations'], $account_id, $txid) && $stmt->execute())
|
( t.account_id = ? AND t.id <= ? AND b.confirmations >= ? )
|
||||||
|
OR ( t.account_id = ? AND t.id <= ? AND t.type IN ( 'Credit_PPS', 'Donation_PPS', 'Fee_PPS', 'TXFee', 'Debit_MP', 'Debit_AP' ) )
|
||||||
|
)");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiiii', $account_id, $txid, $this->config['confirmations'], $account_id, $txid) && $stmt->execute())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,9 +56,16 @@ class Transaction extends Base {
|
|||||||
* @return data array type and total
|
* @return data array type and total
|
||||||
**/
|
**/
|
||||||
public function getTransactionSummary($account_id=NULL) {
|
public function getTransactionSummary($account_id=NULL) {
|
||||||
$sql = "SELECT SUM(t.amount) AS total, t.type AS type FROM $this->table AS t";
|
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||||
|
$sql = "
|
||||||
|
SELECT
|
||||||
|
SUM(t.amount) AS total, t.type AS type
|
||||||
|
FROM transactions AS t
|
||||||
|
LEFT OUTER JOIN blocks AS b
|
||||||
|
ON b.id = t.block_id
|
||||||
|
WHERE ( b.confirmations > 0 OR b.id IS NULL )";
|
||||||
if (!empty($account_id)) {
|
if (!empty($account_id)) {
|
||||||
$sql .= " WHERE t.account_id = ? ";
|
$sql .= " AND t.account_id = ? ";
|
||||||
$this->addParam('i', $account_id);
|
$this->addParam('i', $account_id);
|
||||||
}
|
}
|
||||||
$sql .= " GROUP BY t.type";
|
$sql .= " GROUP BY t.type";
|
||||||
@ -74,9 +84,10 @@ class Transaction extends Base {
|
|||||||
while ($row = $result->fetch_assoc()) {
|
while ($row = $result->fetch_assoc()) {
|
||||||
$aData[$row['type']] = $row['total'];
|
$aData[$row['type']] = $row['total'];
|
||||||
}
|
}
|
||||||
return $aData;
|
// Cache data for a while, query takes long on many rows
|
||||||
|
return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData, 60);
|
||||||
}
|
}
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +109,7 @@ class Transaction extends Base {
|
|||||||
t.amount AS amount,
|
t.amount AS amount,
|
||||||
t.coin_address AS coin_address,
|
t.coin_address AS coin_address,
|
||||||
t.timestamp AS timestamp,
|
t.timestamp AS timestamp,
|
||||||
|
t.txid AS txid,
|
||||||
b.height AS height,
|
b.height AS height,
|
||||||
b.blockhash AS blockhash,
|
b.blockhash AS blockhash,
|
||||||
b.confirmations AS confirmations
|
b.confirmations AS confirmations
|
||||||
@ -144,7 +156,7 @@ class Transaction extends Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($aFilter)) {
|
if (!empty($aFilter)) {
|
||||||
empty($account_id) ? $sql .= " WHERE " : $sql .= " AND ";
|
empty($account_id) ? $sql .= " WHERE " : $sql .= " AND ";
|
||||||
$sql .= implode(' AND ', $aFilter);
|
$sql .= implode(' AND ', $aFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,8 +175,7 @@ class Transaction extends Base {
|
|||||||
$this->num_rows = $row_count;
|
$this->num_rows = $row_count;
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
}
|
}
|
||||||
$this->debug->append('Failed to fetch transactions: ' . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -180,8 +191,7 @@ class Transaction extends Base {
|
|||||||
}
|
}
|
||||||
return $aData;
|
return $aData;
|
||||||
}
|
}
|
||||||
$this->debug->append('Failed to fetch transaction types: ' . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -208,11 +218,11 @@ class Transaction extends Base {
|
|||||||
t.type = 'Donation_PPS'
|
t.type = 'Donation_PPS'
|
||||||
)
|
)
|
||||||
GROUP BY a.username
|
GROUP BY a.username
|
||||||
|
ORDER BY donation DESC
|
||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
$this->debug->append("Failed to fetch website donors: " . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -236,10 +246,7 @@ class Transaction extends Base {
|
|||||||
WHERE archived = 0");
|
WHERE archived = 0");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch())
|
||||||
return $dBalance;
|
return $dBalance;
|
||||||
// Catchall
|
return $this->sqlError();
|
||||||
$this->setErrorMessage('Unable to find locked credits for all users');
|
|
||||||
$this->debug->append('MySQL query failed : ' . $this->mysqli->error);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -272,14 +279,17 @@ class Transaction extends Base {
|
|||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $this->config['confirmations'], $this->config['confirmations'], $this->config['confirmations'], $this->config['confirmations'], $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $this->config['confirmations'], $this->config['confirmations'], $this->config['confirmations'], $this->config['confirmations'], $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
$this->debug->append('Failed to fetch users balance: ' . $this->mysqli->error);
|
return $this->sqlError();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction = new Transaction();
|
$transaction = new Transaction();
|
||||||
|
$transaction->setMemcache($memcache);
|
||||||
$transaction->setDebug($debug);
|
$transaction->setDebug($debug);
|
||||||
$transaction->setMysql($mysqli);
|
$transaction->setMysql($mysqli);
|
||||||
$transaction->setConfig($config);
|
$transaction->setConfig($config);
|
||||||
$transaction->setBlock($block);
|
$transaction->setBlock($block);
|
||||||
$transaction->setUser($user);
|
$transaction->setUser($user);
|
||||||
|
$transaction->setErrorCodes($aErrorCodes);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@ -4,39 +4,12 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
class User {
|
class User extends Base {
|
||||||
private $sError = '';
|
protected $table = 'accounts';
|
||||||
private $userID = false;
|
private $userID = false;
|
||||||
private $table = 'accounts';
|
|
||||||
private $user = array();
|
private $user = array();
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $salt, $config) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->salt = $salt;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->debug->append("Instantiated User class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and set methods
|
// get and set methods
|
||||||
public function setMail($mail) {
|
|
||||||
$this->mail = $mail;
|
|
||||||
}
|
|
||||||
public function setToken($token) {
|
|
||||||
$this->token = $token;
|
|
||||||
}
|
|
||||||
public function setBitcoin($bitcoin) {
|
|
||||||
$this->bitcoin = $bitcoin;
|
|
||||||
}
|
|
||||||
public function setSetting($setting) {
|
|
||||||
$this->setting = $setting;
|
|
||||||
}
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
private function getHash($string) {
|
private function getHash($string) {
|
||||||
return hash('sha256', $string.$this->salt);
|
return hash('sha256', $string.$this->salt);
|
||||||
}
|
}
|
||||||
@ -174,31 +147,6 @@ class User {
|
|||||||
return $pin_hash === $row_pin;
|
return $pin_hash === $row_pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a single row from the table
|
|
||||||
* @param value string Value to search for
|
|
||||||
* @param search Return column to search for
|
|
||||||
* @param field string Search column
|
|
||||||
* @param type string Type of value
|
|
||||||
* @return array Return result
|
|
||||||
**/
|
|
||||||
private function getSingle($value, $search='id', $field='id', $type="i", $lower=false) {
|
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
|
||||||
$sql = "SELECT $search FROM $this->table WHERE";
|
|
||||||
$lower ? $sql .= " LOWER($field) = LOWER(?)" : $sql .= " $field = ?";
|
|
||||||
$sql .= " LIMIT 1";
|
|
||||||
$stmt = $this->mysqli->prepare($sql);
|
|
||||||
if ($this->checkStmt($stmt)) {
|
|
||||||
$stmt->bind_param($type, $value);
|
|
||||||
$stmt->execute();
|
|
||||||
$stmt->bind_result($retval);
|
|
||||||
$stmt->fetch();
|
|
||||||
$stmt->close();
|
|
||||||
return $retval;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all users that have auto payout setup
|
* Get all users that have auto payout setup
|
||||||
* @param none
|
* @param none
|
||||||
@ -243,31 +191,6 @@ class User {
|
|||||||
return $dPercent;
|
return $dPercent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a single row in a table
|
|
||||||
* @param userID int Account ID
|
|
||||||
* @param field string Field to update
|
|
||||||
* @return bool
|
|
||||||
**/
|
|
||||||
private function updateSingle($id, $field) {
|
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
|
||||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET `" . $field['name'] . "` = ? WHERE id = ? LIMIT 1");
|
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute())
|
|
||||||
return true;
|
|
||||||
$this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkStmt($bState) {
|
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
|
||||||
if ($bState ===! true) {
|
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the accounts password
|
* Update the accounts password
|
||||||
* @param userID int User ID
|
* @param userID int User ID
|
||||||
@ -438,12 +361,34 @@ class User {
|
|||||||
// Enforce generation of a new Session ID and delete the old
|
// Enforce generation of a new Session ID and delete the old
|
||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
// Enforce a page reload and point towards login with referrer included, if supplied
|
// Enforce a page reload and point towards login with referrer included, if supplied
|
||||||
$location = @$_SERVER['HTTPS'] ? 'https' . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'] : 'http' . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
|
$port = ($_SERVER["SERVER_PORT"] == "80" or $_SERVER["SERVER_PORT"] == "443") ? "" : (":".$_SERVER["SERVER_PORT"]);
|
||||||
|
$location = @$_SERVER['HTTPS'] ? 'https://' . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'] : 'http://' . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];
|
||||||
if (!empty($from)) $location .= '?page=login&to=' . urlencode($from);
|
if (!empty($from)) $location .= '?page=login&to=' . urlencode($from);
|
||||||
// if (!headers_sent()) header('Location: ' . $location);
|
// if (!headers_sent()) header('Location: ' . $location);
|
||||||
exit('<meta http-equiv="refresh" content="0; url=' . $location . '"/>');
|
exit('<meta http-equiv="refresh" content="0; url=' . $location . '"/>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all users for admin panel
|
||||||
|
**/
|
||||||
|
public function getAllUsers($filter='%') {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT
|
||||||
|
a.id AS id,
|
||||||
|
a.username AS username
|
||||||
|
FROM " . $this->getTableName() . " AS a
|
||||||
|
WHERE a.username LIKE ?
|
||||||
|
GROUP BY username");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $filter) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$aData[$row['id']] = $row['username'];
|
||||||
|
}
|
||||||
|
return $aData;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch this classes table name
|
* Fetch this classes table name
|
||||||
* @return table string This classes table name
|
* @return table string This classes table name
|
||||||
@ -493,7 +438,7 @@ class User {
|
|||||||
**/
|
**/
|
||||||
public function register($username, $password1, $password2, $pin, $email1='', $email2='', $strToken='') {
|
public function register($username, $password1, $password2, $pin, $email1='', $email2='', $strToken='') {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if (strlen($username > 40)) {
|
if (strlen($username) > 40) {
|
||||||
$this->setErrorMessage('Username exceeding character limit');
|
$this->setErrorMessage('Username exceeding character limit');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -687,7 +632,11 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make our class available automatically
|
// Make our class available automatically
|
||||||
$user = new User($debug, $mysqli, SALT, $config);
|
$user = new User();
|
||||||
|
$user->setDebug($debug);
|
||||||
|
$user->setMysql($mysqli);
|
||||||
|
$user->setSalt(SALT);
|
||||||
|
$user->setConfig($config);
|
||||||
$user->setMail($mail);
|
$user->setMail($mail);
|
||||||
$user->setToken($oToken);
|
$user->setToken($oToken);
|
||||||
$user->setBitcoin($bitcoin);
|
$user->setBitcoin($bitcoin);
|
||||||
|
|||||||
@ -1,38 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
die('Hacking attempt');
|
|
||||||
|
|
||||||
class Worker {
|
class Worker extends Base {
|
||||||
private $sError = '';
|
protected $table = 'pool_worker';
|
||||||
private $table = 'pool_worker';
|
|
||||||
|
|
||||||
public function __construct($debug, $mysqli, $user, $share, $config) {
|
|
||||||
$this->debug = $debug;
|
|
||||||
$this->mysqli = $mysqli;
|
|
||||||
$this->user = $user;
|
|
||||||
$this->share = $share;
|
|
||||||
$this->config = $config;
|
|
||||||
$this->debug->append("Instantiated Worker class", 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get and set methods
|
|
||||||
private function setErrorMessage($msg) {
|
|
||||||
$this->sError = $msg;
|
|
||||||
}
|
|
||||||
public function getError() {
|
|
||||||
return $this->sError;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkStmt($bState) {
|
|
||||||
if ($bState ===! true) {
|
|
||||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
|
||||||
$this->setErrorMessage('Internal application Error');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update worker list for a user
|
* Update worker list for a user
|
||||||
@ -61,9 +33,7 @@ class Worker {
|
|||||||
}
|
}
|
||||||
if ($iFailed == 0)
|
if ($iFailed == 0)
|
||||||
return true;
|
return true;
|
||||||
// Catchall
|
return $this->sqlError('E0053', $iFailed);
|
||||||
$this->setErrorMessage('Failed to update ' . $iFailed . ' worker.');
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,20 +41,21 @@ class Worker {
|
|||||||
* @param none
|
* @param none
|
||||||
* @return data array Workers in IDLE state and monitoring enabled
|
* @return data array Workers in IDLE state and monitoring enabled
|
||||||
**/
|
**/
|
||||||
public function getAllIdleWorkers() {
|
public function getAllIdleWorkers($interval=600) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT account_id, id, username
|
SELECT w.account_id AS account_id, w.id AS id, w.username AS username
|
||||||
FROM " . $this->table . " AS w
|
FROM " . $this->share->getTableName() . " AS s
|
||||||
WHERE monitor = 1
|
RIGHT JOIN " . $this->getTableName() . " AS w
|
||||||
AND (
|
ON w.username = s.username
|
||||||
SELECT IFNULL(SUM(IF(our_result = 'Y', 1, 0)), 0) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) = 0");
|
AND our_result = 'Y'
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
WHERE w.monitor = 1
|
||||||
|
AND s.id IS NULL
|
||||||
|
");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $interval) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->sqlError('E0054');
|
||||||
$this->setErrorMessage("Unable to fetch IDLE, monitored workers");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +63,7 @@ class Worker {
|
|||||||
* @param id int Worker ID
|
* @param id int Worker ID
|
||||||
* @return mixed array Worker details
|
* @return mixed array Worker details
|
||||||
**/
|
**/
|
||||||
public function getWorker($id) {
|
public function getWorker($id, $interval=600) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT id, username, password, monitor,
|
SELECT id, username, password, monitor,
|
||||||
@ -100,35 +71,34 @@ class Worker {
|
|||||||
( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all_archive,
|
( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all_archive,
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE
|
WHERE
|
||||||
username = w.username
|
username = w.username
|
||||||
AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) + (
|
) + (
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE
|
WHERE
|
||||||
username = w.username
|
username = w.username
|
||||||
AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) AS hashrate,
|
) AS hashrate,
|
||||||
(
|
(
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) + (
|
) + (
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) AS difficulty
|
) AS difficulty
|
||||||
FROM $this->table AS w
|
FROM $this->table AS w
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
");
|
");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_assoc();
|
return $result->fetch_assoc();
|
||||||
// Catchall
|
return $this->sqlError('E0055');
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,44 +106,90 @@ class Worker {
|
|||||||
* @param account_id int User ID
|
* @param account_id int User ID
|
||||||
* @return mixed array Workers and their settings or false
|
* @return mixed array Workers and their settings or false
|
||||||
**/
|
**/
|
||||||
public function getWorkers($account_id) {
|
public function getWorkers($account_id, $interval=600) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("
|
$stmt = $this->mysqli->prepare("
|
||||||
SELECT id, username, password, monitor,
|
SELECT id, username, password, monitor,
|
||||||
( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all,
|
( SELECT COUNT(id) FROM " . $this->share->getTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all,
|
||||||
( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS count_all_archive,
|
( SELECT COUNT(id) FROM " . $this->share->getArchiveTableName() . " WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)) AS count_all_archive,
|
||||||
(
|
(
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE
|
WHERE
|
||||||
username = w.username
|
username = w.username
|
||||||
AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) + (
|
) + (
|
||||||
SELECT
|
SELECT
|
||||||
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * 65536/600/1000), 0), 0) AS hashrate
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE
|
WHERE
|
||||||
username = w.username
|
username = w.username
|
||||||
AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) AS hashrate,
|
) AS hashrate,
|
||||||
(
|
(
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all, 2), 0)
|
||||||
FROM " . $this->share->getTableName() . "
|
FROM " . $this->share->getTableName() . "
|
||||||
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) + (
|
) + (
|
||||||
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) / count_all_archive, 2), 0)
|
||||||
FROM " . $this->share->getArchiveTableName() . "
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
) AS difficulty
|
) AS difficulty
|
||||||
FROM $this->table AS w
|
FROM $this->table AS w
|
||||||
WHERE account_id = ?");
|
WHERE account_id = ?");
|
||||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $interval, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_all(MYSQLI_ASSOC);
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
// Catchall
|
return $this->sqlError('E0056');
|
||||||
$this->setErrorMessage('Failed to fetch workers for your account');
|
}
|
||||||
$this->debug->append('Fetching workers failed: ' . $this->mysqli->error);
|
|
||||||
return false;
|
/**
|
||||||
|
* Fetch all workers for admin panel
|
||||||
|
* @param limit int
|
||||||
|
* @return mixed array Workers and their settings or false
|
||||||
|
**/
|
||||||
|
public function getAllWorkers($iLimit=0, $interval=600) {
|
||||||
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT id, username, password, monitor,
|
||||||
|
IFNULL(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty), 0) AS difficulty,
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
|
FROM " . $this->share->getTableName() . "
|
||||||
|
WHERE
|
||||||
|
username = w.username
|
||||||
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
) + (
|
||||||
|
SELECT
|
||||||
|
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
|
||||||
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
|
WHERE
|
||||||
|
username = w.username
|
||||||
|
AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
) AS hashrate,
|
||||||
|
((
|
||||||
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 2), 0)
|
||||||
|
FROM " . $this->share->getTableName() . "
|
||||||
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
) + (
|
||||||
|
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 2), 0)
|
||||||
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
)) / ((
|
||||||
|
SELECT COUNT(id)
|
||||||
|
FROM " . $this->share->getTableName() . "
|
||||||
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
) + (
|
||||||
|
SELECT COUNT(id)
|
||||||
|
FROM " . $this->share->getArchiveTableName() . "
|
||||||
|
WHERE username = w.username AND time > DATE_SUB(now(), INTERVAL ? SECOND)
|
||||||
|
)) AS avg_difficulty
|
||||||
|
FROM $this->table AS w
|
||||||
|
ORDER BY hashrate DESC LIMIT ?");
|
||||||
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iiiiiiiii', $interval, $interval, $interval, $interval, $interval, $interval, $interval, $interval, $iLimit) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
|
return $result->fetch_all(MYSQLI_ASSOC);
|
||||||
|
return $this->sqlError('E0057');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -183,10 +199,15 @@ class Worker {
|
|||||||
**/
|
**/
|
||||||
public function getCountAllActiveWorkers() {
|
public function getCountAllActiveWorkers() {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("SELECT IFNULL(IF(our_result='Y', COUNT(DISTINCT username), 0), 0) AS total FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)");
|
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||||
|
$stmt = $this->mysqli->prepare("
|
||||||
|
SELECT COUNT(DISTINCT(username)) AS total
|
||||||
|
FROM " . $this->share->getTableName() . "
|
||||||
|
WHERE our_result = 'Y'
|
||||||
|
AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)");
|
||||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
|
||||||
return $result->fetch_object()->total;
|
return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->total);
|
||||||
return false;
|
return $this->sqlError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,22 +222,20 @@ class Worker {
|
|||||||
public function addWorker($account_id, $workerName, $workerPassword) {
|
public function addWorker($account_id, $workerName, $workerPassword) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
if ('' === $workerName || '' === $workerPassword) {
|
if ('' === $workerName || '' === $workerPassword) {
|
||||||
$this->setErrorMessage('Worker name and/or password may not be empty');
|
$this->setErrorMessage($this->getErrorMsg('E0058'));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$username = $this->user->getUserName($account_id);
|
$username = $this->user->getUserName($account_id);
|
||||||
$workerName = "$username.$workerName";
|
$workerName = "$username.$workerName";
|
||||||
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, username, password) VALUES(?, ?, ?)");
|
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, username, password) VALUES(?, ?, ?)");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('iss', $account_id, $workerName, $workerPassword)) {
|
||||||
$stmt->bind_param('iss', $account_id, $workerName, $workerPassword);
|
|
||||||
if (!$stmt->execute()) {
|
if (!$stmt->execute()) {
|
||||||
$this->setErrorMessage( 'Failed to add worker' );
|
if ($stmt->sqlstate == '23000') return $this->sqlError('E0059');
|
||||||
if ($stmt->sqlstate == '23000') $this->setErrorMessage( 'Worker already exists' );
|
} else {
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return $this->sqlError('E0060');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -228,16 +247,19 @@ class Worker {
|
|||||||
public function deleteWorker($account_id, $id) {
|
public function deleteWorker($account_id, $id) {
|
||||||
$this->debug->append("STA " . __METHOD__, 4);
|
$this->debug->append("STA " . __METHOD__, 4);
|
||||||
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE account_id = ? AND id = ?");
|
$stmt = $this->mysqli->prepare("DELETE FROM $this->table WHERE account_id = ? AND id = ?");
|
||||||
if ($this->checkStmt($stmt)) {
|
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $account_id, $id) && $stmt->execute() && $stmt->affected_rows == 1)
|
||||||
$stmt->bind_param('ii', $account_id, $id);
|
|
||||||
if ($stmt->execute() && $stmt->affected_rows == 1) {
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
return $this->sqlError('E0061');
|
||||||
$this->setErrorMessage( 'Unable to delete worker' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$worker = new Worker($debug, $mysqli, $user, $share, $config);
|
$worker = new Worker();
|
||||||
|
$worker->setDebug($debug);
|
||||||
|
$worker->setMysql($mysqli);
|
||||||
|
$worker->setMemcache($memcache);
|
||||||
|
$worker->setShare($share);
|
||||||
|
$worker->setConfig($config);
|
||||||
|
$worker->setUser($user);
|
||||||
|
$worker->setErrorCodes($aErrorCodes);
|
||||||
|
|
||||||
|
?>
|
||||||
|
|||||||
@ -123,6 +123,13 @@ $aSettings['statistics'][] = array(
|
|||||||
'name' => 'statistics_block_count', 'value' => $setting->getValue('statistics_block_count'),
|
'name' => 'statistics_block_count', 'value' => $setting->getValue('statistics_block_count'),
|
||||||
'tooltip' => 'Blocks to fetch for the block statistics page.'
|
'tooltip' => 'Blocks to fetch for the block statistics page.'
|
||||||
);
|
);
|
||||||
|
$aSettings['statistics'][] = array(
|
||||||
|
'display' => 'Show block average', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes' ),
|
||||||
|
'default' => 0,
|
||||||
|
'name' => 'statistics_show_block_average', 'value' => $setting->getValue('statistics_show_block_average'),
|
||||||
|
'tooltip' => 'Show block average in block statistics page.'
|
||||||
|
);
|
||||||
$aSettings['statistics'][] = array(
|
$aSettings['statistics'][] = array(
|
||||||
'display' => 'Pool Hashrate Modifier', 'type' => 'select',
|
'display' => 'Pool Hashrate Modifier', 'type' => 'select',
|
||||||
'options' => array( '1' => 'KH/s', '0.001' => 'MH/s', '0.000001' => 'GH/s' ),
|
'options' => array( '1' => 'KH/s', '0.001' => 'MH/s', '0.000001' => 'GH/s' ),
|
||||||
@ -144,6 +151,28 @@ $aSettings['statistics'][] = array(
|
|||||||
'name' => 'statistics_personal_hashrate_modifier', 'value' => $setting->getValue('statistics_personal_hashrate_modifier'),
|
'name' => 'statistics_personal_hashrate_modifier', 'value' => $setting->getValue('statistics_personal_hashrate_modifier'),
|
||||||
'tooltip' => 'Auto-adjust displayed personal hashrates to a certain limit.'
|
'tooltip' => 'Auto-adjust displayed personal hashrates to a certain limit.'
|
||||||
);
|
);
|
||||||
|
$aSettings['statistics'][] = array(
|
||||||
|
'display' => 'Enable Google analytics', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes' ),
|
||||||
|
'default' => 0,
|
||||||
|
'name' => 'statistics_analytics_enabled', 'value' => $setting->getValue('statistics_analytics_enabled'),
|
||||||
|
'tooltip' => 'Enable or Disable Google Analytics.'
|
||||||
|
);
|
||||||
|
$aSettings['statistics'][] = array(
|
||||||
|
'display' => 'Google Analytics Code', 'type' => 'textarea',
|
||||||
|
'size' => 20,
|
||||||
|
'height' => 12,
|
||||||
|
'default' => 'Code from Google Analytics',
|
||||||
|
'name' => 'statistics_analytics_code', 'value' => $setting->getValue('statistics_analytics_code'),
|
||||||
|
'tooltip' => '.'
|
||||||
|
);
|
||||||
|
$aSettings['acl'][] = array(
|
||||||
|
'display' => 'Hide news post author', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes' ),
|
||||||
|
'default' => 0,
|
||||||
|
'name' => 'acl_hide_news_author', 'value' => $setting->getValue('acl_hide_news_author'),
|
||||||
|
'tooltip' => 'Should the news author username be hidden.'
|
||||||
|
);
|
||||||
$aSettings['acl'][] = array(
|
$aSettings['acl'][] = array(
|
||||||
'display' => 'Pool Statistics', 'type' => 'select',
|
'display' => 'Pool Statistics', 'type' => 'select',
|
||||||
'options' => array( 0 => 'Private', 1 => 'Public'),
|
'options' => array( 0 => 'Private', 1 => 'Public'),
|
||||||
@ -166,11 +195,25 @@ $aSettings['acl'][] = array(
|
|||||||
'tooltip' => 'Make the round statistics page private (users only) or public.'
|
'tooltip' => 'Make the round statistics page private (users only) or public.'
|
||||||
);
|
);
|
||||||
$aSettings['acl'][] = array(
|
$aSettings['acl'][] = array(
|
||||||
'display' => 'Round Transactions', 'type' => 'select',
|
'display' => 'Block Finder Statistics', 'type' => 'select',
|
||||||
'options' => array( 0 => 'Admins', 1 => 'Public'),
|
'options' => array( 0 => 'Private', 1 => 'Public'),
|
||||||
'default' => 0,
|
'default' => 1,
|
||||||
'name' => 'acl_round_transactions', 'value' => $setting->getValue('acl_round_transactions'),
|
'name' => 'acl_blockfinder_statistics', 'value' => $setting->getValue('acl_blockfinder_statistics'),
|
||||||
'tooltip' => 'Display all transactions regardless of admin status.'
|
'tooltip' => 'Make the Block Finder Statistics page private (users only) or public.'
|
||||||
|
);
|
||||||
|
$aSettings['acl'][] = array(
|
||||||
|
'display' => 'Uptime Statistics', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'Private', 1 => 'Public'),
|
||||||
|
'default' => 1,
|
||||||
|
'name' => 'acl_uptime_statistics', 'value' => $setting->getValue('acl_uptime_statistics'),
|
||||||
|
'tooltip' => 'Make the uptime statistics page private (users only) or public.'
|
||||||
|
);
|
||||||
|
$aSettings['system'][] = array(
|
||||||
|
'display' => 'E-mail address for system error notifications', 'type' => 'text',
|
||||||
|
'size' => 25,
|
||||||
|
'default' => 'test@example.com',
|
||||||
|
'name' => 'system_error_email', 'value' => $setting->getValue('system_error_email'),
|
||||||
|
'tooltip' => 'The email address for system errors notifications, like cronjobs failures.'
|
||||||
);
|
);
|
||||||
$aSettings['system'][] = array(
|
$aSettings['system'][] = array(
|
||||||
'display' => 'Disable e-mail confirmations', 'type' => 'select',
|
'display' => 'Disable e-mail confirmations', 'type' => 'select',
|
||||||
@ -228,6 +271,34 @@ $aSettings['system'][] = array(
|
|||||||
'name' => 'disable_contactform', 'value' => $setting->getValue('disable_contactform'),
|
'name' => 'disable_contactform', 'value' => $setting->getValue('disable_contactform'),
|
||||||
'tooltip' => 'Enable or Disable Contactform. Users will not be able to use the contact form.'
|
'tooltip' => 'Enable or Disable Contactform. Users will not be able to use the contact form.'
|
||||||
);
|
);
|
||||||
|
$aSettings['system'][] = array(
|
||||||
|
'display' => 'Disable Donors Page', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes'),
|
||||||
|
'default' => 1,
|
||||||
|
'name' => 'disable_donors', 'value' => $setting->getValue('disable_donors'),
|
||||||
|
'tooltip' => 'Showing Donors page in Navigation.'
|
||||||
|
);
|
||||||
|
$aSettings['system'][] = array(
|
||||||
|
'display' => 'Disable About Page', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes'),
|
||||||
|
'default' => 1,
|
||||||
|
'name' => 'disable_about', 'value' => $setting->getValue('disable_about'),
|
||||||
|
'tooltip' => 'Showing About page in Navigation.'
|
||||||
|
);
|
||||||
|
$aSettings['system'][] = array(
|
||||||
|
'display' => 'Disable Live Dashboard', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes'),
|
||||||
|
'default' => 0,
|
||||||
|
'name' => 'disable_dashboard', 'value' => $setting->getValue('disable_dashboard'),
|
||||||
|
'tooltip' => 'Disable live updates on the dashboard to reduce server load.'
|
||||||
|
);
|
||||||
|
$aSettings['system'][] = array(
|
||||||
|
'display' => 'Disable Dashboard API', 'type' => 'select',
|
||||||
|
'options' => array( 0 => 'No', 1 => 'Yes'),
|
||||||
|
'default' => 0,
|
||||||
|
'name' => 'disable_dashboard_api', 'value' => $setting->getValue('disable_dashboard_api'),
|
||||||
|
'tooltip' => 'Disable dashboard API entirely to reduce server load.'
|
||||||
|
);
|
||||||
$aSettings['recaptcha'][] = array(
|
$aSettings['recaptcha'][] = array(
|
||||||
'display' => 'Enable re-Captcha', 'type' => 'select',
|
'display' => 'Enable re-Captcha', 'type' => 'select',
|
||||||
'options' => array( 0 => 'No', 1 => 'Yes' ),
|
'options' => array( 0 => 'No', 1 => 'Yes' ),
|
||||||
@ -249,5 +320,12 @@ $aSettings['recaptcha'][] = array(
|
|||||||
'name' => 'recaptcha_public_key', 'value' => $setting->getValue('recaptcha_public_key'),
|
'name' => 'recaptcha_public_key', 'value' => $setting->getValue('recaptcha_public_key'),
|
||||||
'tooltip' => 'Your public key as given by your re-Captcha account.'
|
'tooltip' => 'Your public key as given by your re-Captcha account.'
|
||||||
);
|
);
|
||||||
|
$aSettings['monitoring'][] = array(
|
||||||
|
'display' => 'Uptime Robot Private API Key', 'type' => 'text',
|
||||||
|
'size' => 100,
|
||||||
|
'default' => '<API KEY>|<MONITOR ID>,<API KEY>|<MONITOR ID>, ...',
|
||||||
|
'name' => 'monitoring_uptimerobot_api_keys', 'value' => $setting->getValue('monitoring_uptimerobot_api_keys'),
|
||||||
|
'tooltip' => 'Create per-monitor API keys and save them here to propagate your uptime statistics.'
|
||||||
|
);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
71
public/include/config/error_codes.inc.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
$aErrorCodes['OK'] = 'OK';
|
||||||
|
$aErrorCodes['E0001'] = 'Out of Order Share Detected';
|
||||||
|
$aErrorCodes['E0002'] = 'Upstream shares not found';
|
||||||
|
$aErrorCodes['E0003'] = 'Failed to change shares order';
|
||||||
|
$aErrorCodes['E0004'] = 'Failed to reset previous block';
|
||||||
|
$aErrorCodes['E0005'] = 'Unable to fetch blocks upstream share';
|
||||||
|
$aErrorCodes['E0006'] = 'Unable to conenct to RPC server backend';
|
||||||
|
$aErrorCodes['E0007'] = 'Out of Order Share detected, autofixed';
|
||||||
|
$aErrorCodes['E0008'] = 'Failed to delete archived shares';
|
||||||
|
$aErrorCodes['E0009'] = 'Cron disabled by admin';
|
||||||
|
$aErrorCodes['E0010'] = 'Unable set payout as processed';
|
||||||
|
$aErrorCodes['E0011'] = 'No new unaccounted blocks';
|
||||||
|
$aErrorCodes['E0012'] = 'No share_id found for block';
|
||||||
|
$aErrorCodes['E0013'] = 'No shares found for block';
|
||||||
|
$aErrorCodes['E0014'] = 'Failed marking block as accounted';
|
||||||
|
$aErrorCodes['E0015'] = 'Potential Double Payout detected';
|
||||||
|
$aErrorCodes['E0016'] = 'Failed to delete accounted shares';
|
||||||
|
$aErrorCodes['E0017'] = 'Failed to update Uptime Robot status';
|
||||||
|
$aErrorCodes['E0018'] = 'Cron disbaled due to errors';
|
||||||
|
$aErrorCodes['E0019'] = "SQL Query failed: %s";
|
||||||
|
$aErrorCodes['E0020'] = 'Internal error while executing SQL';
|
||||||
|
$aErrorCodes['E0021'] = 'Unable to fetch invitiations send from your account';
|
||||||
|
$aErrorCodes['E0022'] = 'Unable to create invitation record';
|
||||||
|
$aErrorCodes['E0023'] = 'Invalid E-Mail Address';
|
||||||
|
$aErrorCodes['E0024'] = 'Message may only contain alphanumeric characters';
|
||||||
|
$aErrorCodes['E0025'] = 'This email is already registered as an account';
|
||||||
|
$aErrorCodes['E0026'] = 'A pending invitation for this address already exists';
|
||||||
|
$aErrorCodes['E0027'] = 'Unable to generate invitation token: %s';
|
||||||
|
$aErrorCodes['E0028'] = 'Unable to send email to recipient';
|
||||||
|
$aErrorCodes['E0029'] = 'Unable to send invitation';
|
||||||
|
$aErrorCodes['E0030'] = 'Unable to fetch a valid token for this invitation';
|
||||||
|
$aErrorCodes['E0031'] = 'Failed to send e-mail via mail() function';
|
||||||
|
$aErrorCodes['E0032'] = 'Failed to run API call: %s';
|
||||||
|
$aErrorCodes['E0033'] = 'Failed to store uptime status: %s';
|
||||||
|
$aErrorCodes['E0034'] = 'Subjcet may only contain alphanumeric characters';
|
||||||
|
$aErrorCodes['E0035'] = 'Failed to add news record';
|
||||||
|
$aErrorCodes['E0036'] = 'Failed to delete news record';
|
||||||
|
$aErrorCodes['E0037'] = 'Failed to update news record';
|
||||||
|
$aErrorCodes['E0038'] = 'Failed to fetch news record entry';
|
||||||
|
$aErrorCodes['E0039'] = 'Failed to fetch news records';
|
||||||
|
$aErrorCodes['E0040'] = 'Failed to fetch active news records';
|
||||||
|
$aErrorCodes['E0041'] = 'Failed to fetch existing notification records';
|
||||||
|
$aErrorCodes['E0042'] = 'Failed to fetch active notification records';
|
||||||
|
$aErrorCodes['E0043'] = 'Unable to add new notification';
|
||||||
|
$aErrorCodes['E0044'] = 'Failed to fetch notifications for user account';
|
||||||
|
$aErrorCodes['E0045'] = 'Failed fetching notification settings for user account';
|
||||||
|
$aErrorCodes['E0046'] = 'Failed to fetch notification setting for user account';
|
||||||
|
$aErrorCodes['E0047'] = "Failed to update %s settings";
|
||||||
|
$aErrorCodes['E0048'] = 'Failed to check for existing active payouts';
|
||||||
|
$aErrorCodes['E0049'] = 'Unable to create new payout request';
|
||||||
|
$aErrorCodes['E0050'] = 'Failed to fetch unprocessed payouts';
|
||||||
|
$aErrorCodes['E0051'] = 'Failed to mark payout as processed';
|
||||||
|
$aErrorCodes['E0052'] = 'Unable to find valid upstream share for block: %s';
|
||||||
|
$aErrorCodes['E0053'] = 'Failed to update %s workers';
|
||||||
|
$aErrorCodes['E0054'] = 'Unable to fetch IDLE, monitored workers';
|
||||||
|
$aErrorCodes['E0055'] = 'Failed fetching worker details';
|
||||||
|
$aErrorCodes['E0056'] = 'Failed to fetch workers for your account';
|
||||||
|
$aErrorCodes['E0057'] = 'Failed to fetch workers for admin panel';
|
||||||
|
$aErrorCodes['E0058'] = 'Worker name and/or password must not be empty';
|
||||||
|
$aErrorCodes['E0059'] = 'Worker already exists';
|
||||||
|
$aErrorCodes['E0060'] = 'Failed to add new worker';
|
||||||
|
$aErrorCodes['E0061'] = 'Failed to delete worker';
|
||||||
|
$aErrorCodes['E0062'] = 'Block has no share_id, not running payouts';
|
||||||
|
$aErrorCodes['E0063'] = 'Upstream share already assigned to previous block';
|
||||||
|
$aErrorCodes['E0064'] = 'Failed to create transaction record';
|
||||||
|
?>
|
||||||
@ -20,6 +20,17 @@ define('DEBUG', 0);
|
|||||||
// SALT used to hash passwords
|
// SALT used to hash passwords
|
||||||
define('SALT', 'PLEASEMAKEMESOMETHINGRANDOM');
|
define('SALT', 'PLEASEMAKEMESOMETHINGRANDOM');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Underlying coin algorithm that you are mining on. Set this to whatever your coin needs:
|
||||||
|
*
|
||||||
|
* Options:
|
||||||
|
* sha256d : SHA coins like Bitcoin
|
||||||
|
* scrypt : Scrypt based coins like Litecoin
|
||||||
|
* Default:
|
||||||
|
* scrypt : Scrypt is default
|
||||||
|
**/
|
||||||
|
$config['algorithm'] = 'scrypt';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database configuration
|
* Database configuration
|
||||||
*
|
*
|
||||||
@ -58,6 +69,18 @@ $config['wallet']['host'] = 'localhost:19334';
|
|||||||
$config['wallet']['username'] = 'testnet';
|
$config['wallet']['username'] = 'testnet';
|
||||||
$config['wallet']['password'] = 'testnet';
|
$config['wallet']['password'] = 'testnet';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getting Started Config
|
||||||
|
*
|
||||||
|
* This is displayed on GettingStarted Page
|
||||||
|
* to make it more dynamic
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
$config['gettingstarted']['coinname'] = 'Litecoin';
|
||||||
|
$config['gettingstarted']['coinurl'] = 'http://www.litecoin.org';
|
||||||
|
$config['gettingstarted']['stratumport'] = '3333';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API configuration to fetch prices for set currency
|
* API configuration to fetch prices for set currency
|
||||||
*
|
*
|
||||||
@ -86,7 +109,6 @@ $config['price']['url'] = 'https://btc-e.com';
|
|||||||
$config['price']['target'] = '/api/2/ltc_usd/ticker';
|
$config['price']['target'] = '/api/2/ltc_usd/ticker';
|
||||||
$config['price']['currency'] = 'USD';
|
$config['price']['currency'] = 'USD';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automatic payout thresholds
|
* Automatic payout thresholds
|
||||||
*
|
*
|
||||||
@ -123,6 +145,20 @@ $config['accounts']['invitations']['count'] = 5;
|
|||||||
// Currency system used in this pool, default: `LTC`
|
// Currency system used in this pool, default: `LTC`
|
||||||
$config['currency'] = 'LTC';
|
$config['currency'] = 'LTC';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coin Target in seconds
|
||||||
|
*
|
||||||
|
* Explanation
|
||||||
|
* Target time for coins to be generated
|
||||||
|
*
|
||||||
|
* Fastcoin: 12 seconds
|
||||||
|
* Litecoin: 2,5 minutes = 150 seconds
|
||||||
|
* Feathercoin: 2,5 minutes = 150 seconds
|
||||||
|
* Bitcoin: 10 minutes = 600 seconds
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
$config['cointarget'] = '150';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default transaction fee to apply to user transactions
|
* Default transaction fee to apply to user transactions
|
||||||
*
|
*
|
||||||
@ -231,9 +267,20 @@ $config['fees'] = 0;
|
|||||||
* type = `blockavg`
|
* type = `blockavg`
|
||||||
* blockcount = 10
|
* blockcount = 10
|
||||||
**/
|
**/
|
||||||
|
/**
|
||||||
|
* $config['pplns']['shares']['type'] = 'dynamic';
|
||||||
|
* Dynamic target adjustment allows the blockavg target to adjust faster to share counts
|
||||||
|
* while still tracking round share averages by using a percentage of the current round shares
|
||||||
|
* to alter the pplns blockavg target this is useful with the nature of many alt coins low and fast
|
||||||
|
* adjusting difficulties and quick round times
|
||||||
|
* reverse_payout is useful to even out payouts for fast round times when even steady miners
|
||||||
|
* are missing share submissions for the current round
|
||||||
|
**/
|
||||||
$config['pplns']['shares']['default'] = 4000000;
|
$config['pplns']['shares']['default'] = 4000000;
|
||||||
$config['pplns']['shares']['type'] = 'blockavg';
|
$config['pplns']['shares']['type'] = 'blockavg';
|
||||||
$config['pplns']['blockavg']['blockcount'] = 10;
|
$config['pplns']['blockavg']['blockcount'] = 10;
|
||||||
|
$config['pplns']['reverse_payout'] = false; // add user shares from archive even if user not in current round
|
||||||
|
$config['pplns']['dynamic']['percent'] = 30; // percentage of round shares factored into block average when using dynamic type
|
||||||
|
|
||||||
// Pool target difficulty as set in pushpoold configuration file
|
// Pool target difficulty as set in pushpoold configuration file
|
||||||
// Please also read this for stratum: https://github.com/TheSerapher/php-mpos/wiki/FAQ
|
// Please also read this for stratum: https://github.com/TheSerapher/php-mpos/wiki/FAQ
|
||||||
@ -297,10 +344,6 @@ $config['pps']['reward']['default'] = 50;
|
|||||||
$config['pps']['reward']['type'] = 'blockavg';
|
$config['pps']['reward']['type'] = 'blockavg';
|
||||||
$config['pps']['blockavg']['blockcount'] = 10;
|
$config['pps']['blockavg']['blockcount'] = 10;
|
||||||
|
|
||||||
// pps base payout target, default 16 = difficulty 1 shares for vardiff
|
|
||||||
// (1/(65536 * difficulty) * reward) = (reward / (pow(2,32) * difficulty) * pow(2, 16))
|
|
||||||
$config['pps_target'] = 16; // do not change unless you know what it does
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memcache configuration
|
* Memcache configuration
|
||||||
*
|
*
|
||||||
@ -413,4 +456,19 @@ $config['cookie']['secure'] = false;
|
|||||||
**/
|
**/
|
||||||
$config['smarty']['cache'] = 0;
|
$config['smarty']['cache'] = 0;
|
||||||
$config['smarty']['cache_lifetime'] = 30;
|
$config['smarty']['cache_lifetime'] = 30;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System load setting
|
||||||
|
*
|
||||||
|
* This will disable loading of some API calls in case the system
|
||||||
|
* loads exceeds the defined max setting. Useful to temporaily suspend
|
||||||
|
* live statistics on a server that is too busy to deal with requests.
|
||||||
|
*
|
||||||
|
* Options
|
||||||
|
* max = float, maximum system load
|
||||||
|
*
|
||||||
|
* Defaults:
|
||||||
|
* max = 10.0
|
||||||
|
**/
|
||||||
|
$config['system']['load']['max'] = 10.0;
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -3,9 +3,15 @@
|
|||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY')) die('Hacking attempt');
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
$aDonors = $transaction->getDonations();
|
if ($setting->getValue('disable_donors')) {
|
||||||
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Donors are currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||||
|
$smarty->assign("CONTENT", "disabled.tpl");
|
||||||
|
} else {
|
||||||
|
$aDonors = $transaction->getDonations();
|
||||||
|
|
||||||
|
// Tempalte specifics
|
||||||
|
$smarty->assign("DONORS", $aDonors);
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
}
|
||||||
|
|
||||||
// Tempalte specifics
|
|
||||||
$smarty->assign("DONORS", $aDonors);
|
|
||||||
$smarty->assign("CONTENT", "default.tpl");
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -4,6 +4,12 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
// Tempalte specifics
|
if ($setting->getValue('disable_about')) {
|
||||||
$smarty->assign("CONTENT", "default.tpl");
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Donors are currently disabled. Please try again later.', 'TYPE' => 'errormsg');
|
||||||
|
$smarty->assign("CONTENT", "disabled.tpl");
|
||||||
|
} else {
|
||||||
|
// Tempalte specifics
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ if ($user->isAuthenticated()) {
|
|||||||
if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) {
|
if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) {
|
||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings');
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings');
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update settings', 'TYPE' => 'errormsg');
|
$_SESSION['POPUP'][] = array('CONTENT' => $notification->getError(), 'TYPE' => 'errormsg');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ case 'prop':
|
|||||||
// Data array for template
|
// Data array for template
|
||||||
foreach ($aCrons as $strCron) {
|
foreach ($aCrons as $strCron) {
|
||||||
$aCronStatus[$strCron] = array(
|
$aCronStatus[$strCron] = array(
|
||||||
|
'disabled' => $monitoring->getStatus($strCron . '_disabled'),
|
||||||
'exit' => $monitoring->getStatus($strCron . '_status'),
|
'exit' => $monitoring->getStatus($strCron . '_status'),
|
||||||
'active' => $monitoring->getStatus($strCron . '_active'),
|
'active' => $monitoring->getStatus($strCron . '_active'),
|
||||||
'runtime' => $monitoring->getStatus($strCron . '_runtime'),
|
'runtime' => $monitoring->getStatus($strCron . '_runtime'),
|
||||||
|
|||||||
18
public/include/pages/admin/poolworkers.inc.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
// Check user to ensure they are admin
|
||||||
|
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||||
|
header("HTTP/1.1 404 Page not found");
|
||||||
|
die("404 Page not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
$iActiveWorkers = $worker->getCountAllActiveWorkers();
|
||||||
|
$aWorkers = $worker->getAllWorkers($iActiveWorkers);
|
||||||
|
|
||||||
|
$smarty->assign('WORKERS', $aWorkers);
|
||||||
|
|
||||||
|
$smarty->assign('CONTENT', 'default.tpl');
|
||||||
|
|
||||||
|
?>
|
||||||
86
public/include/pages/admin/reports.inc.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
// Check user to ensure they are admin
|
||||||
|
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||||
|
header("HTTP/1.1 404 Page not found");
|
||||||
|
die("404 Page not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||||
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
|
|
||||||
|
$aUserList = $user->getAllUsers('%');
|
||||||
|
|
||||||
|
$iHeight = 0;
|
||||||
|
$iUserId = 0;
|
||||||
|
$filter = 0;
|
||||||
|
$userName = 'None';
|
||||||
|
if (@$_REQUEST['id']) {
|
||||||
|
$iUserId = $_REQUEST['id'];
|
||||||
|
$userName = $user->getUserName($_REQUEST['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$setting->getValue('statistics_block_count') ? $iLimit = $setting->getValue('statistics_block_count') : $iLimit = 20;
|
||||||
|
if (@$_REQUEST['limit']) {
|
||||||
|
$iLimit = $_REQUEST['limit'];
|
||||||
|
if ( $iLimit > 1000 )
|
||||||
|
$iLimit = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
|
||||||
|
$iHeight = @$roundstats->getNextBlockForStats($_REQUEST['height'], $iLimit);
|
||||||
|
if (!$iHeight) {
|
||||||
|
$aBlock = $block->getLast();
|
||||||
|
$iHeight = $aBlock['height'];
|
||||||
|
}
|
||||||
|
} else if (@$_REQUEST['prev'] && !empty($_REQUEST['height'])) {
|
||||||
|
$iHeight = $_REQUEST['height'];
|
||||||
|
} else if (!empty($_REQUEST['height']) && is_numeric($_REQUEST['height'])) {
|
||||||
|
$iHeight = $_REQUEST['height'];
|
||||||
|
} else {
|
||||||
|
$aBlock = $block->getLast();
|
||||||
|
$iHeight = $aBlock['height'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@$_REQUEST['search']) {
|
||||||
|
$iHeight = $roundstats->searchForBlockHeight($_REQUEST['search']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@$_REQUEST['filter']) {
|
||||||
|
$filter = $_REQUEST['filter'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$aBlocksData = array();
|
||||||
|
if ( $iUserId ) {
|
||||||
|
if ($filter) {
|
||||||
|
$aBlocksData = $roundstats->getAllReportBlocksFoundHeight($iHeight, $iLimit);
|
||||||
|
} else {
|
||||||
|
$aBlocksData = $roundstats->getUserReportBlocksFoundHeight($iHeight, $iLimit, $iUserId);
|
||||||
|
}
|
||||||
|
foreach($aBlocksData as $key => $aData) {
|
||||||
|
$aBlocksData[$key]['pplns_shares'] = @$roundstats->getPPLNSRoundShares($aData['height']);
|
||||||
|
$aBlocksData[$key]['user'] = @$roundstats->getRoundStatsForUser($aData['height'], $iUserId);
|
||||||
|
$aBlocksData[$key]['user_credit'] = @$roundstats->getUserRoundTransHeight($aData['height'], $iUserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$smarty->assign('REPORTDATA', $aBlocksData);
|
||||||
|
$smarty->assign("USERLIST", $aUserList);
|
||||||
|
$smarty->assign("USERNAME", $userName);
|
||||||
|
$smarty->assign("USERID", $iUserId);
|
||||||
|
$smarty->assign("BLOCKLIMIT", $iLimit);
|
||||||
|
$smarty->assign("HEIGHT", $iHeight);
|
||||||
|
$smarty->assign("FILTER", $filter);
|
||||||
|
} else {
|
||||||
|
$debug->append('Using cached page', 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->isAuthenticated(false)) {
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
} else {
|
||||||
|
$smarty->assign("CONTENT", "empty");
|
||||||
|
}
|
||||||
|
?>
|
||||||
@ -31,23 +31,11 @@ if (@$_POST['query']) {
|
|||||||
$aUsers = $statistics->getAllUserStats($_POST['query']);
|
$aUsers = $statistics->getAllUserStats($_POST['query']);
|
||||||
|
|
||||||
// Add additional stats to each user
|
// Add additional stats to each user
|
||||||
// This is not optimized yet, best is a proper SQL
|
|
||||||
// Query against the stats table? Currently cached though.
|
|
||||||
foreach ($aUsers as $iKey => $aUser) {
|
foreach ($aUsers as $iKey => $aUser) {
|
||||||
$aBalance = $transaction->getBalance($aUser['id']);
|
$aBalance = $transaction->getBalance($aUser['id']);
|
||||||
$aUser['balance'] = $aBalance['confirmed'];
|
$aUser['balance'] = $aBalance['confirmed'];
|
||||||
$aUser['hashrate'] = $statistics->getUserHashrate($aUser['id']);
|
$aUser['hashrate'] = $statistics->getUserHashrate($aUser['id']);
|
||||||
if ($aUser['shares'] > 0) {
|
$aUser['estimates'] = $statistics->getUserEstimates($aRoundShares, $aUser['shares'], $aUser['donate_percent'], $aUser['no_fees']);
|
||||||
$aUser['payout']['est_block'] = round(( (int)$aUser['shares'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3);
|
|
||||||
$aUser['payout']['est_fee'] = round(($config['fees'] / 100) * $aUser['payout']['est_block'], 3);
|
|
||||||
$aUser['payout']['est_donation'] = round((( $aUser['donate_percent'] / 100) * ($aUser['payout']['est_block'] - $aUser['payout']['est_fee'])), 3);
|
|
||||||
$aUser['payout']['est_payout'] = round($aUser['payout']['est_block'] - $aUser['payout']['est_donation'] - $aUser['payout']['est_fee'], 3);
|
|
||||||
} else {
|
|
||||||
$aUser['payout']['est_block'] = 0;
|
|
||||||
$aUser['payout']['est_fee'] = 0;
|
|
||||||
$aUser['payout']['est_donation'] = 0;
|
|
||||||
$aUser['payout']['est_payout'] = 0;
|
|
||||||
}
|
|
||||||
$aUsers[$iKey] = $aUser;
|
$aUsers[$iKey] = $aUser;
|
||||||
}
|
}
|
||||||
// Assign our variables
|
// Assign our variables
|
||||||
|
|||||||
@ -13,13 +13,14 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
|||||||
$debug->append('No cached version available, fetching from backend', 3);
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
if ($bitcoin->can_connect() === true){
|
if ($bitcoin->can_connect() === true){
|
||||||
$dBalance = $bitcoin->query('getbalance');
|
$dBalance = $bitcoin->query('getbalance');
|
||||||
$dGetInfo = $bitcoin->query('getinfo');
|
$aGetInfo = $bitcoin->query('getinfo');
|
||||||
if (is_array($dGetInfo) && array_key_exists('newmint', $dGetInfo)) {
|
if (is_array($aGetInfo) && array_key_exists('newmint', $aGetInfo)) {
|
||||||
$dNewmint = $dGetInfo['newmint'];
|
$dNewmint = $aGetInfo['newmint'];
|
||||||
} else {
|
} else {
|
||||||
$dNewmint = -1;
|
$dNewmint = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$aGetInfo = array('errors' => 'Unable to connect');
|
||||||
$dBalance = 0;
|
$dBalance = 0;
|
||||||
$dNewmint = -1;
|
$dNewmint = -1;
|
||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||||
@ -45,6 +46,7 @@ $smarty->assign("BALANCE", $dBalance);
|
|||||||
$smarty->assign("COLDCOINS", $dColdCoins);
|
$smarty->assign("COLDCOINS", $dColdCoins);
|
||||||
$smarty->assign("LOCKED", $dLockedBalance);
|
$smarty->assign("LOCKED", $dLockedBalance);
|
||||||
$smarty->assign("NEWMINT", $dNewmint);
|
$smarty->assign("NEWMINT", $dNewmint);
|
||||||
|
$smarty->assign("COININFO", $aGetInfo);
|
||||||
|
|
||||||
// Tempalte specifics
|
// Tempalte specifics
|
||||||
$smarty->assign("CONTENT", "default.tpl");
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
|||||||
@ -3,8 +3,22 @@
|
|||||||
// Make sure we are called from index.php
|
// Make sure we are called from index.php
|
||||||
if (!defined('SECURITY')) die('Hacking attempt');
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
// Check if the API is activated
|
// Check if the system is enabled
|
||||||
$api->isActive();
|
if ($setting->getValue('disable_dashboard_api')) {
|
||||||
|
echo $api->get_json(array('error' => 'disabled'));
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
// System load check
|
||||||
|
if ($load = @sys_getloadavg()) {
|
||||||
|
if (isset($config['system']['load']['max']) && $load[0] > $config['system']['load']['max']) {
|
||||||
|
header('HTTP/1.1 503 Too busy, try again later');
|
||||||
|
die('Server too busy. Please try again later.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supress master template
|
||||||
|
$supress_master = 1;
|
||||||
|
|
||||||
// Check user token and access level permissions
|
// Check user token and access level permissions
|
||||||
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
|
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
|
||||||
@ -32,27 +46,85 @@ $dPoolHashrate = $statistics->getCurrentHashrate($interval);
|
|||||||
if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate;
|
if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate;
|
||||||
$dPersonalHashrate = $statistics->getUserHashrate($user_id, $interval);
|
$dPersonalHashrate = $statistics->getUserHashrate($user_id, $interval);
|
||||||
$dPersonalSharerate = $statistics->getUserSharerate($user_id, $interval);
|
$dPersonalSharerate = $statistics->getUserSharerate($user_id, $interval);
|
||||||
|
$dPersonalShareDifficulty = $statistics->getUserShareDifficulty($user_id, $interval);
|
||||||
$statistics->setGetCache(true);
|
$statistics->setGetCache(true);
|
||||||
|
|
||||||
// Use caches for this one
|
// Use caches for this one
|
||||||
$aUserRoundShares = $statistics->getUserShares($user_id);
|
$aUserRoundShares = $statistics->getUserShares($user_id);
|
||||||
$aRoundShares = $statistics->getRoundShares();
|
$aRoundShares = $statistics->getRoundShares();
|
||||||
$aEstimates = $statistics->getUserEstimates($aRoundShares, $aUserRoundShares, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id));
|
|
||||||
|
if ($config['payout_system'] != 'pps') {
|
||||||
|
$aEstimates = $statistics->getUserEstimates($aRoundShares, $aUserRoundShares, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id));
|
||||||
|
$dUnpaidShares = 0;
|
||||||
|
} else {
|
||||||
|
$dUnpaidShares = $statistics->getUserUnpaidPPSShares($user_id, $setting->getValue('pps_last_share_id'));
|
||||||
|
if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
||||||
|
$pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount']));
|
||||||
|
} else {
|
||||||
|
if ($config['pps']['reward']['type'] == 'block') {
|
||||||
|
if ($aLastBlock = $block->getLast()) {
|
||||||
|
$pps_reward = $aLastBlock['amount'];
|
||||||
|
} else {
|
||||||
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ppsvalue = round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['target_bits']), 12);
|
||||||
|
$aEstimates = $statistics->getUserEstimates($dPersonalSharerate, $dPersonalShareDifficulty, $user->getUserDonatePercent($user_id), $user->getUserNoFee($user_id), $ppsvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
$iTotalRoundShares = $aRoundShares['valid'] + $aRoundShares['invalid'];
|
||||||
|
if ($iTotalRoundShares > 0) {
|
||||||
|
$dUserInvalidPercent = round($aUserRoundShares['invalid'] / $iTotalRoundShares * 100, 2);
|
||||||
|
$dPoolInvalidPercent = round($aRoundShares['invalid'] / $iTotalRoundShares * 100, 2);
|
||||||
|
} else {
|
||||||
|
$dUserInvalidPercent = 0;
|
||||||
|
$dPoolInvalidPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Apply pool modifiers
|
// Apply pool modifiers
|
||||||
$dPersonalHashrateAdjusted = $dPersonalHashrate * $dPersonalHashrateModifier;
|
$dPersonalHashrateAdjusted = $dPersonalHashrate * $dPersonalHashrateModifier;
|
||||||
$dPoolHashrateAdjusted = $dPoolHashrate * $dPoolHashrateModifier;
|
$dPoolHashrateAdjusted = $dPoolHashrate * $dPoolHashrateModifier;
|
||||||
$dNetworkHashrateAdjusted = $dNetworkHashrate / 1000 * $dNetworkHashrateModifier;
|
$dNetworkHashrateAdjusted = $dNetworkHashrate / 1000 * $dNetworkHashrateModifier;
|
||||||
|
|
||||||
|
// Worker information
|
||||||
|
$aWorkers = $worker->getWorkers($user_id, $interval);
|
||||||
|
|
||||||
|
// Coin price
|
||||||
|
$aPrice = $setting->getValue('price');
|
||||||
|
|
||||||
|
// Round progress
|
||||||
|
$iEstShares = $statistics->getEstimatedShares($dDifficulty);
|
||||||
|
if ($iEstShares > 0 && $aRoundShares['valid'] > 0) {
|
||||||
|
$dEstPercent = round(100 / $iEstShares * $aRoundShares['valid'], 2);
|
||||||
|
} else {
|
||||||
|
$dEstPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Output JSON format
|
// Output JSON format
|
||||||
$data = array(
|
$data = array(
|
||||||
'raw' => array( 'personal' => array( 'hashrate' => $dPersonalHashrate ), 'pool' => array( 'hashrate' => $dPoolHashrate ), 'network' => array( 'hashrate' => $dNetworkHashrate / 1000 ) ),
|
'raw' => array( 'personal' => array( 'hashrate' => $dPersonalHashrate ), 'pool' => array( 'hashrate' => $dPoolHashrate ), 'network' => array( 'hashrate' => $dNetworkHashrate / 1000 ) ),
|
||||||
'personal' => array ( 'hashrate' => $dPersonalHashrateAdjusted, 'sharerate' => $dPersonalSharerate, 'shares' => $aUserRoundShares, 'balance' => $transaction->getBalance($user_id), 'estimates' => $aEstimates),
|
'personal' => array (
|
||||||
'pool' => array( 'hashrate' => $dPoolHashrateAdjusted, 'shares' => $aRoundShares ),
|
'hashrate' => $dPersonalHashrateAdjusted, 'sharerate' => $dPersonalSharerate, 'sharedifficulty' => $dPersonalShareDifficulty,
|
||||||
|
'shares' => array('valid' => $aUserRoundShares['valid'], 'invalid' => $aUserRoundShares['invalid'], 'invalid_percent' => $dUserInvalidPercent, 'unpaid' => $dUnpaidShares ),
|
||||||
|
'balance' => $transaction->getBalance($user_id), 'estimates' => $aEstimates, 'workers' => $aWorkers ),
|
||||||
|
'pool' => array(
|
||||||
|
'info' => array(
|
||||||
|
'name' => $setting->getValue('website_name'),
|
||||||
|
'currency' => $config['currency']
|
||||||
|
),
|
||||||
|
'workers' => $worker->getCountAllActiveWorkers(), 'hashrate' => $dPoolHashrateAdjusted,
|
||||||
|
'shares' => array( 'valid' => $aRoundShares['valid'], 'invalid' => $aRoundShares['invalid'], 'invalid_percent' => $dPoolInvalidPercent, 'estimated' => $iEstShares, 'progress' => $dEstPercent ),
|
||||||
|
'price' => $aPrice,
|
||||||
|
'difficulty' => pow(2, $config['difficulty'] - 16),
|
||||||
|
'target_bits' => $config['difficulty']
|
||||||
|
),
|
||||||
|
'system' => array( 'load' => sys_getloadavg() ),
|
||||||
'network' => array( 'hashrate' => $dNetworkHashrateAdjusted, 'difficulty' => $dDifficulty, 'block' => $iBlock ),
|
'network' => array( 'hashrate' => $dNetworkHashrateAdjusted, 'difficulty' => $dDifficulty, 'block' => $iBlock ),
|
||||||
);
|
);
|
||||||
echo $api->get_json($data);
|
|
||||||
|
|
||||||
// Supress master template
|
echo $api->get_json($data);
|
||||||
$supress_master = 1;
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
64
public/include/pages/api/getnavbardata.inc.php
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
// Check if the API is activated
|
||||||
|
$api->isActive();
|
||||||
|
|
||||||
|
// Fetch RPC information
|
||||||
|
if ($bitcoin->can_connect() === true) {
|
||||||
|
$dNetworkHashrate = $bitcoin->getnetworkhashps();
|
||||||
|
$dDifficulty = $bitcoin->getdifficulty();
|
||||||
|
$iBlock = $bitcoin->getblockcount();
|
||||||
|
} else {
|
||||||
|
$dNetworkHashrate = 0;
|
||||||
|
$dDifficulty = 1;
|
||||||
|
$iBlock = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some settings
|
||||||
|
if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300;
|
||||||
|
if ( ! $dPoolHashrateModifier = $setting->getValue('statistics_pool_hashrate_modifier') ) $dPoolHashrateModifier = 1;
|
||||||
|
if ( ! $dNetworkHashrateModifier = $setting->getValue('statistics_network_hashrate_modifier') ) $dNetworkHashrateModifier = 1;
|
||||||
|
|
||||||
|
// Fetch raw data
|
||||||
|
$statistics->setGetCache(false);
|
||||||
|
$dPoolHashrate = $statistics->getCurrentHashrate($interval);
|
||||||
|
if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate;
|
||||||
|
$statistics->setGetCache(true);
|
||||||
|
|
||||||
|
// Apply pool modifiers
|
||||||
|
$dPoolHashrateAdjusted = $dPoolHashrate * $dPoolHashrateModifier;
|
||||||
|
$dNetworkHashrateAdjusted = $dNetworkHashrate / 1000 * $dNetworkHashrateModifier;
|
||||||
|
|
||||||
|
// Use caches for this one
|
||||||
|
$aRoundShares = $statistics->getRoundShares();
|
||||||
|
|
||||||
|
$iTotalRoundShares = $aRoundShares['valid'] + $aRoundShares['invalid'];
|
||||||
|
if ($iTotalRoundShares > 0) {
|
||||||
|
$dPoolInvalidPercent = round($aRoundShares['invalid'] / $iTotalRoundShares * 100, 2);
|
||||||
|
} else {
|
||||||
|
$dUserInvalidPercent = 0;
|
||||||
|
$dPoolInvalidPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round progress
|
||||||
|
$iEstShares = $statistics->getEstimatedShares($dDifficulty);
|
||||||
|
if ($iEstShares > 0 && $aRoundShares['valid'] > 0) {
|
||||||
|
$dEstPercent = round(100 / $iEstShares * $aRoundShares['valid'], 2);
|
||||||
|
} else {
|
||||||
|
$dEstPercent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output JSON format
|
||||||
|
$data = array(
|
||||||
|
'raw' => array( 'workers' => $worker->getCountAllActiveWorkers(), 'pool' => array( 'hashrate' => $dPoolHashrate ) ),
|
||||||
|
'pool' => array( 'workers' => $worker->getCountAllActiveWorkers(), 'hashrate' => $dPoolHashrateAdjusted, 'estimated' => $iEstShares, 'progress' => $dEstPercent ),
|
||||||
|
'network' => array( 'hashrate' => $dNetworkHashrateAdjusted, 'difficulty' => $dDifficulty, 'block' => $iBlock ),
|
||||||
|
);
|
||||||
|
echo $api->get_json($data);
|
||||||
|
|
||||||
|
// Supress master template
|
||||||
|
$supress_master = 1;
|
||||||
|
?>
|
||||||
@ -47,6 +47,7 @@ if (!empty($aLastBlock)) {
|
|||||||
|
|
||||||
// Output JSON format
|
// Output JSON format
|
||||||
$data = array(
|
$data = array(
|
||||||
|
'pool_name' => $setting->getValue('website_name'),
|
||||||
'hashrate' => $iCurrentPoolHashrate,
|
'hashrate' => $iCurrentPoolHashrate,
|
||||||
'efficiency' => $dEfficiency,
|
'efficiency' => $dEfficiency,
|
||||||
'workers' => $worker->getCountAllActiveWorkers(),
|
'workers' => $worker->getCountAllActiveWorkers(),
|
||||||
|
|||||||
65
public/include/pages/api/gettopcontributors.inc.php
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
// Check user token and access level permissions
|
||||||
|
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
|
||||||
|
|
||||||
|
// Some settings
|
||||||
|
if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300;
|
||||||
|
|
||||||
|
// Fetch raw data
|
||||||
|
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
||||||
|
$aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||||
|
|
||||||
|
// Honor the anonymous flag
|
||||||
|
foreach ($aContributorsHashes as $iKey => $aData) {
|
||||||
|
if ($user->isAdmin($user_id)) {
|
||||||
|
$aContributorsHashes = array(
|
||||||
|
'account' => $aData['account'],
|
||||||
|
'hashrate' => $aData['hashrate']
|
||||||
|
);
|
||||||
|
} else if ($aData['is_anonymous'] == 1) {
|
||||||
|
$aContributorsHashes = array(
|
||||||
|
'account' => 'anonymous',
|
||||||
|
'hashrate' => $aData['hashrate']
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$aContributorsHashes = array(
|
||||||
|
'account' => $aData['account'],
|
||||||
|
'hashrate' => $aData['hashrate']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Honor the anonymous flag
|
||||||
|
foreach ($aContributorsShares as $iKey => $aData) {
|
||||||
|
if ($user->isAdmin($user_id)) {
|
||||||
|
$aContributorsShares[$iKey] = array(
|
||||||
|
'account' => $aData['account'],
|
||||||
|
'shares' => $aData['shares']
|
||||||
|
);
|
||||||
|
} else if ($aData['is_anonymous'] == 1) {
|
||||||
|
$aContributorsShares[$iKey] = array(
|
||||||
|
'account' => 'anonymous',
|
||||||
|
'shares' => $aData['shares']
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$aContributorsShares[$iKey] = array(
|
||||||
|
'account' => $aData['account'],
|
||||||
|
'shares' => $aData['shares']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output JSON format
|
||||||
|
$data = array(
|
||||||
|
'hashes' => $aContributorsHashes,
|
||||||
|
'shares' => $aContributorsShares
|
||||||
|
);
|
||||||
|
echo $api->get_json($data);
|
||||||
|
|
||||||
|
// Supress master template
|
||||||
|
$supress_master = 1;
|
||||||
|
?>
|
||||||
@ -9,12 +9,16 @@ $api->isActive();
|
|||||||
// Check user token
|
// Check user token
|
||||||
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
|
$user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']);
|
||||||
|
|
||||||
|
// Fetch transaction summary
|
||||||
|
$aTransactionSummary = $transaction->getTransactionSummary($user_id);
|
||||||
|
|
||||||
// Output JSON format
|
// Output JSON format
|
||||||
$data = array(
|
$data = array(
|
||||||
'username' => $user->getUsername($user_id),
|
'username' => $user->getUsername($user_id),
|
||||||
'shares' => $statistics->getUserShares($user_id),
|
'shares' => $statistics->getUserShares($user_id),
|
||||||
'hashrate' => $statistics->getUserHashrate($user_id),
|
'hashrate' => $statistics->getUserHashrate($user_id),
|
||||||
'sharerate' => $statistics->getUserSharerate($user_id)
|
'sharerate' => $statistics->getUserSharerate($user_id),
|
||||||
|
'transactions' => $aTransactionSummary
|
||||||
);
|
);
|
||||||
echo $api->get_json($data);
|
echo $api->get_json($data);
|
||||||
|
|
||||||
|
|||||||
@ -6,35 +6,28 @@ if (!defined('SECURITY')) die('Hacking attempt');
|
|||||||
if ($user->isAuthenticated()) {
|
if ($user->isAuthenticated()) {
|
||||||
if (! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300;
|
if (! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300;
|
||||||
// Defaults to get rid of PHP Notice warnings
|
// Defaults to get rid of PHP Notice warnings
|
||||||
|
$dNetworkHashrate = 0;
|
||||||
$dDifficulty = 1;
|
$dDifficulty = 1;
|
||||||
$aRoundShares = 1;
|
$aRoundShares = 1;
|
||||||
|
|
||||||
// Only run these if the user is logged in
|
|
||||||
$aRoundShares = $statistics->getRoundShares();
|
$aRoundShares = $statistics->getRoundShares();
|
||||||
|
$dDifficulty = 1;
|
||||||
|
$dNetworkHashrate = 1;
|
||||||
|
$iBlock = 0;
|
||||||
if ($bitcoin->can_connect() === true) {
|
if ($bitcoin->can_connect() === true) {
|
||||||
$dDifficulty = $bitcoin->query('getdifficulty');
|
$dDifficulty = $bitcoin->getdifficulty();
|
||||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
$dNetworkHashrate = $bitcoin->getnetworkhashps();
|
||||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
$iBlock = $bitcoin->getblockcount();
|
||||||
}
|
|
||||||
|
|
||||||
// Always fetch this since we need for ministats header
|
|
||||||
$aRoundShares = $statistics->getRoundShares();
|
|
||||||
if ($bitcoin->can_connect() === true) {
|
|
||||||
$dDifficulty = $bitcoin->query('getdifficulty');
|
|
||||||
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
|
|
||||||
$dDifficulty = $dDifficulty['proof-of-work'];
|
|
||||||
try { $dNetworkHashrate = $bitcoin->query('getnetworkhashps') / 1000; } catch (Exception $e) {
|
|
||||||
// Maybe we are SHA
|
|
||||||
try { $dNetworkHashrate = $bitcoin->query('gethashespersec') / 1000; } catch (Exception $e) {
|
|
||||||
$dNetworkHashrate = 0;
|
|
||||||
}
|
|
||||||
$dNetworkHashrate = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$dNetworkHashrate = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch some data
|
// Fetch some data
|
||||||
|
// Round progress
|
||||||
|
$iEstShares = $statistics->getEstimatedShares($dDifficulty);
|
||||||
|
if ($iEstShares > 0 && $aRoundShares['valid'] > 0) {
|
||||||
|
$dEstPercent = round(100 / $iEstShares * $aRoundShares['valid'], 2);
|
||||||
|
} else {
|
||||||
|
$dEstPercent = 0;
|
||||||
|
}
|
||||||
if (!$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers()) $iCurrentActiveWorkers = 0;
|
if (!$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers()) $iCurrentActiveWorkers = 0;
|
||||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||||
$iCurrentPoolShareRate = $statistics->getCurrentShareRate();
|
$iCurrentPoolShareRate = $statistics->getCurrentShareRate();
|
||||||
@ -43,6 +36,10 @@ if ($user->isAuthenticated()) {
|
|||||||
if ($iCurrentPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $iCurrentPoolHashrate;
|
if ($iCurrentPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $iCurrentPoolHashrate;
|
||||||
|
|
||||||
// Make it available in Smarty
|
// Make it available in Smarty
|
||||||
|
$smarty->assign('DISABLED_DASHBOARD', $setting->getValue('disable_dashboard'));
|
||||||
|
$smarty->assign('DISABLED_DASHBOARD_API', $setting->getValue('disable_dashboard_api'));
|
||||||
|
$smarty->assign('ESTIMATES', array('shares' => $iEstShares, 'percent' => $dEstPercent));
|
||||||
|
$smarty->assign('NETWORK', array('difficulty' => $dDifficulty, 'block' => $iBlock));
|
||||||
$smarty->assign('INTERVAL', $interval / 60);
|
$smarty->assign('INTERVAL', $interval / 60);
|
||||||
$smarty->assign('CONTENT', 'default.tpl');
|
$smarty->assign('CONTENT', 'default.tpl');
|
||||||
}
|
}
|
||||||
|
|||||||
9
public/include/pages/error.inc.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY'))
|
||||||
|
die('Hacking attempt');
|
||||||
|
|
||||||
|
// Tempalte specifics
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
?>
|
||||||
9
public/include/pages/error/404.inc.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY'))
|
||||||
|
die('Hacking attempt');
|
||||||
|
|
||||||
|
// Tempalte specifics
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
?>
|
||||||
@ -4,6 +4,10 @@
|
|||||||
if (!defined('SECURITY'))
|
if (!defined('SECURITY'))
|
||||||
die('Hacking attempt');
|
die('Hacking attempt');
|
||||||
|
|
||||||
|
$smarty->assign("SITESTRATUMPORT", $config['gettingstarted']['stratumport']);
|
||||||
|
$smarty->assign("SITECOINNAME", $config['gettingstarted']['coinname']);
|
||||||
|
$smarty->assign("SITECOINURL", $config['gettingstarted']['coinurl']);
|
||||||
|
|
||||||
// Tempalte specifics
|
// Tempalte specifics
|
||||||
$smarty->assign("CONTENT", "default.tpl");
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -16,6 +16,8 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
|||||||
$aNews[$key]['content'] = Markdown::defaultTransform($aData['content']);
|
$aNews[$key]['content'] = Markdown::defaultTransform($aData['content']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$smarty->assign("HIDEAUTHOR", $setting->getValue('acl_hide_news_author'));
|
||||||
$smarty->assign("NEWS", $aNews);
|
$smarty->assign("NEWS", $aNews);
|
||||||
} else {
|
} else {
|
||||||
$debug->append('Using cached page', 3);
|
$debug->append('Using cached page', 3);
|
||||||
|
|||||||
@ -7,7 +7,8 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST
|
|||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'You are not allowed to login during maintenace.', 'TYPE' => 'info');
|
$_SESSION['POPUP'][] = array('CONTENT' => 'You are not allowed to login during maintenace.', 'TYPE' => 'info');
|
||||||
} else if ($user->checkLogin(@$_POST['username'], @$_POST['password']) ) {
|
} else if ($user->checkLogin(@$_POST['username'], @$_POST['password']) ) {
|
||||||
empty($_POST['to']) ? $to = $_SERVER['PHP_SELF'] : $to = $_POST['to'];
|
empty($_POST['to']) ? $to = $_SERVER['PHP_SELF'] : $to = $_POST['to'];
|
||||||
$location = @$_SERVER['HTTPS'] === true ? 'https' : 'http' . '://' . $_SERVER['SERVER_NAME'] . $to;
|
$port = ($_SERVER["SERVER_PORT"] == "80" or $_SERVER["SERVER_PORT"] == "443") ? "" : (":".$_SERVER["SERVER_PORT"]);
|
||||||
|
$location = @$_SERVER['HTTPS'] === true ? 'https://' . $_SERVER['SERVER_NAME'] . $port . $to : 'http://' . $_SERVER['SERVER_NAME'] . $port . $to;
|
||||||
if (!headers_sent()) header('Location: ' . $location);
|
if (!headers_sent()) header('Location: ' . $location);
|
||||||
exit('<meta http-equiv="refresh" content="0; url=' . $location . '"/>');
|
exit('<meta http-equiv="refresh" content="0; url=' . $location . '"/>');
|
||||||
} else if (@$_POST['username'] && @$_POST['password']) {
|
} else if (@$_POST['username'] && @$_POST['password']) {
|
||||||
|
|||||||
@ -16,6 +16,7 @@ if (is_array($aNews)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tempalte specifics
|
// Tempalte specifics
|
||||||
|
$smarty->assign("HIDEAUTHOR", $settings->getValue('acl_hide_news_author'));
|
||||||
$smarty->assign("NEWS", $aNews);
|
$smarty->assign("NEWS", $aNews);
|
||||||
$smarty->assign("CONTENT", "default.tpl");
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist
|
|||||||
if ($rsp->is_valid) {
|
if ($rsp->is_valid) {
|
||||||
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key')));
|
$smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key')));
|
||||||
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
||||||
if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2'], $token)) {
|
if ($user->register(@$_POST['username'], @$_POST['password1'], @$_POST['password2'], @$_POST['pin'], @$_POST['email1'], @$_POST['email2'], $token)) {
|
||||||
! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||||
@ -39,7 +39,7 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist
|
|||||||
// Captcha disabled
|
// Captcha disabled
|
||||||
} else {
|
} else {
|
||||||
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
isset($_POST['token']) ? $token = $_POST['token'] : $token = '';
|
||||||
if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2'], $token)) {
|
if ($user->register(@$_POST['username'], @$_POST['password1'], @$_POST['password2'], @$_POST['pin'], @$_POST['email1'], @$_POST['email2'], $token)) {
|
||||||
! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||||
|
|||||||
29
public/include/pages/statistics/blockfinder.inc.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
// Grab Block Finder
|
||||||
|
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||||
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
|
$getBlocksSolvedbyAccount = $statistics->getBlocksSolvedbyAccount();
|
||||||
|
$smarty->assign("BLOCKSSOLVEDBYACCOUNT", $getBlocksSolvedbyAccount);
|
||||||
|
|
||||||
|
if(isset($_SESSION['USERDATA']['id'])){
|
||||||
|
$getBlocksSolvedbyWorker = $statistics->getBlocksSolvedbyWorker($_SESSION['USERDATA']['id']);
|
||||||
|
$smarty->assign("BLOCKSSOLVEDBYWORKER", $getBlocksSolvedbyWorker);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$debug->append('Using cached page', 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public / private page detection
|
||||||
|
if ($setting->getValue('acl_blockfinder_statistics')) {
|
||||||
|
$smarty->assign("CONTENT", "finder.tpl");
|
||||||
|
} else if ($user->isAuthenticated()) {
|
||||||
|
$smarty->assign("CONTENT", "finder.tpl");
|
||||||
|
} else {
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
}
|
||||||
|
?>
|
||||||
@ -8,11 +8,84 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
|||||||
$debug->append('No cached version available, fetching from backend', 3);
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
// Grab the last blocks found
|
// Grab the last blocks found
|
||||||
$setting->getValue('statistics_block_count') ? $iLimit = $setting->getValue('statistics_block_count') : $iLimit = 20;
|
$setting->getValue('statistics_block_count') ? $iLimit = $setting->getValue('statistics_block_count') : $iLimit = 20;
|
||||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
if (@$_REQUEST['limit'] && !empty($_REQUEST['limit']) && is_numeric($_REQUEST['limit'])) {
|
||||||
|
$iLimit = $_REQUEST['limit'];
|
||||||
|
if ( $iLimit > 40 )
|
||||||
|
$iLimit = 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iHeight = 0;
|
||||||
|
if (@$_REQUEST['next'] && !empty($_REQUEST['height']) && is_numeric($_REQUEST['height'])) {
|
||||||
|
$iHeight = @$roundstats->getNextBlockForStats($_REQUEST['height'], $iLimit);
|
||||||
|
if (!$iHeight) {
|
||||||
|
$iBlock = $block->getLast();
|
||||||
|
$iHeight = $iBlock['height'];
|
||||||
|
}
|
||||||
|
} else if (@$_REQUEST['prev'] && !empty($_REQUEST['height']) && is_numeric($_REQUEST['height'])) {
|
||||||
|
$iHeight = $_REQUEST['height'];
|
||||||
|
} else if (empty($_REQUEST['height'])) {
|
||||||
|
$aBlock = $block->getLast();
|
||||||
|
$iHeight = $aBlock['height'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = false;
|
||||||
|
if (@$_REQUEST['test'] && $user->isAdmin($_SESSION['USERDATA']['id'])) {
|
||||||
|
$test = true;
|
||||||
|
$count = 10;
|
||||||
|
$percent = 30;
|
||||||
|
if (@$_REQUEST['count'] && is_numeric($_REQUEST['count']))
|
||||||
|
$count = $_REQUEST['count'];
|
||||||
|
if (@$_REQUEST['percent'] && is_numeric($_REQUEST['percent']))
|
||||||
|
$percent = $_REQUEST['percent'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$aBlocksFoundData = $statistics->getBlocksFoundHeight($iHeight, $iLimit);
|
||||||
|
$use_average = false;
|
||||||
|
if ($config['payout_system'] == 'pplns') {
|
||||||
|
foreach($aBlocksFoundData as $key => $aData) {
|
||||||
|
$aBlocksFoundData[$key]['pplns_shares'] = $roundstats->getPPLNSRoundShares($aData['height']);
|
||||||
|
if ($setting->getValue('statistics_show_block_average') && !$test) {
|
||||||
|
$aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $config['pplns']['blockavg']['blockcount']));
|
||||||
|
$use_average = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ($config['payout_system'] == 'prop' || $config['payout_system'] == 'pps') {
|
||||||
|
if ($setting->getValue('statistics_show_block_average') && !$test) {
|
||||||
|
foreach($aBlocksFoundData as $key => $aData) {
|
||||||
|
$aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $config['pplns']['blockavg']['blockcount']));
|
||||||
|
$use_average = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// show test data in graph
|
||||||
|
if ($test) {
|
||||||
|
$use_average = true;
|
||||||
|
foreach($aBlocksFoundData as $key => $aData) {
|
||||||
|
if ($_REQUEST['test'] == 1) {
|
||||||
|
$aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $count));
|
||||||
|
} else if ($_REQUEST['test'] == 2) {
|
||||||
|
$aBlocksFoundData[$key]['block_avg'] = round($block->getAvgBlockShares($aData['height'], $count) * (100 - $percent) / 100 + $aData['shares'] * $percent / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$iHours = 24;
|
||||||
|
$aPoolStatistics = $statistics->getPoolStatsHours($iHours);
|
||||||
|
$iFirstBlockFound = $statistics->getFirstBlockFound();
|
||||||
|
$iTimeSinceFirstBlockFound = (time() - $iFirstBlockFound);
|
||||||
|
|
||||||
|
// Coin target block generation time, default to 150 (2.5 minutes)
|
||||||
|
@$config['cointarget'] ? $smarty->assign("COINGENTIME", $config['cointarget']) : $smarty->assign("COINGENTIME", 150);
|
||||||
|
|
||||||
|
// Past blocks found, max 4 weeks back
|
||||||
|
$iFoundBlocksByTime = $statistics->getLastBlocksbyTime();
|
||||||
// Propagate content our template
|
// Propagate content our template
|
||||||
|
$smarty->assign("FIRSTBLOCKFOUND", $iTimeSinceFirstBlockFound);
|
||||||
|
$smarty->assign("LASTBLOCKSBYTIME", $iFoundBlocksByTime);
|
||||||
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
|
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
|
||||||
$smarty->assign("BLOCKLIMIT", $iLimit);
|
$smarty->assign("BLOCKLIMIT", $iLimit);
|
||||||
|
$smarty->assign("USEBLOCKAVERAGE", $use_average);
|
||||||
|
$smarty->assign("POOLSTATS", $aPoolStatistics);
|
||||||
} else {
|
} else {
|
||||||
$debug->append('Using cached page', 3);
|
$debug->append('Using cached page', 3);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
|||||||
// Top hash contributors
|
// Top hash contributors
|
||||||
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
||||||
|
|
||||||
// Grab the last 10 blocks found
|
// Grab the last 5 blocks found as a quick overview
|
||||||
$iLimit = 5;
|
$iLimit = 5;
|
||||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||||
count($aBlocksFoundData) > 0 ? $aBlockData = $aBlocksFoundData[0] : $aBlockData = array();
|
count($aBlocksFoundData) > 0 ? $aBlockData = $aBlocksFoundData[0] : $aBlockData = array();
|
||||||
@ -34,9 +34,8 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
|||||||
$iCurrentPoolHashrate > 0 ? $iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000) : $iEstTime = 0;
|
$iCurrentPoolHashrate > 0 ? $iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000) : $iEstTime = 0;
|
||||||
|
|
||||||
// Time since last block
|
// Time since last block
|
||||||
$now = new DateTime( "now" );
|
|
||||||
if (!empty($aBlockData)) {
|
if (!empty($aBlockData)) {
|
||||||
$dTimeSinceLast = ($now->getTimestamp() - $aBlockData['time']);
|
$dTimeSinceLast = (time() - $aBlockData['time']);
|
||||||
if ($dTimeSinceLast < 0) $dTimeSinceLast = 0;
|
if ($dTimeSinceLast < 0) $dTimeSinceLast = 0;
|
||||||
} else {
|
} else {
|
||||||
$dTimeSinceLast = 0;
|
$dTimeSinceLast = 0;
|
||||||
|
|||||||
@ -6,26 +6,40 @@ if (!defined('SECURITY')) die('Hacking attempt');
|
|||||||
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||||
$debug->append('No cached version available, fetching from backend', 3);
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
|
|
||||||
if (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
|
if (@$_REQUEST['search']) {
|
||||||
$iKey = $roundstats->getNextBlock($_REQUEST['height']);
|
$_REQUEST['height'] = $roundstats->searchForBlockHeight($_REQUEST['search']);
|
||||||
} else if (@$_REQUEST['prev'] && !empty($_REQUEST['height'])) {
|
|
||||||
$iKey = $roundstats->getPreviousBlock($_REQUEST['height']);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (empty($_REQUEST['height'])) {
|
|
||||||
$iBlock = $block->getLast();
|
|
||||||
$iKey = $iBlock['height'];
|
|
||||||
} else {
|
|
||||||
$iKey = $_REQUEST['height'];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iKey, $user->isAdmin(@$_SESSION['USERDATA']['id']));
|
if (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
|
||||||
$aRoundShareStats = $roundstats->getRoundStatsForAccounts($iKey, $user->isAdmin(@$_SESSION['USERDATA']['id']));
|
$iHeight = @$roundstats->getNextBlock($_REQUEST['height']);
|
||||||
|
if (!$iHeight) {
|
||||||
if ($user->isAdmin(@$_SESSION['USERDATA']['id']) || $setting->getValue('acl_round_transactions')) {
|
$iBlock = $block->getLast();
|
||||||
$aUserRoundTransactions = $roundstats->getAllRoundTransactions($iKey, @$_SESSION['USERDATA']['id']);
|
$iHeight = $iBlock['height'];
|
||||||
|
}
|
||||||
|
} else if (@$_REQUEST['prev'] && !empty($_REQUEST['height'])) {
|
||||||
|
$iHeight = $roundstats->getPreviousBlock($_REQUEST['height']);
|
||||||
|
} else if (empty($_REQUEST['height'])) {
|
||||||
|
$iBlock = $block->getLast();
|
||||||
|
$iHeight = $iBlock['height'];
|
||||||
} else {
|
} else {
|
||||||
$aUserRoundTransactions = $roundstats->getUserRoundTransactions($iKey, @$_SESSION['USERDATA']['id']);
|
$iHeight = $_REQUEST['height'];
|
||||||
|
}
|
||||||
|
$_REQUEST['height'] = $iHeight;
|
||||||
|
|
||||||
|
$iPPLNSShares = 0;
|
||||||
|
$aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iHeight);
|
||||||
|
$aRoundShareStats = $roundstats->getRoundStatsForAccounts($iHeight);
|
||||||
|
$aUserRoundTransactions = $roundstats->getAllRoundTransactions($iHeight);
|
||||||
|
|
||||||
|
if ($config['payout_system'] == 'pplns') {
|
||||||
|
$aPPLNSRoundShares = $roundstats->getPPLNSRoundStatsForAccounts($iHeight);
|
||||||
|
foreach($aPPLNSRoundShares as $aData) {
|
||||||
|
$iPPLNSShares += $aData['pplns_valid'];
|
||||||
|
}
|
||||||
|
$block_avg = $block->getAvgBlockShares($iHeight, $config['pplns']['blockavg']['blockcount']);
|
||||||
|
$smarty->assign('PPLNSROUNDSHARES', $aPPLNSRoundShares);
|
||||||
|
$smarty->assign("PPLNSSHARES", $iPPLNSShares);
|
||||||
|
$smarty->assign("BLOCKAVGCOUNT", $config['pplns']['blockavg']['blockcount']);
|
||||||
|
$smarty->assign("BLOCKAVERAGE", $block_avg );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propagate content our template
|
// Propagate content our template
|
||||||
|
|||||||
27
public/include/pages/statistics/uptime.inc.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// Make sure we are called from index.php
|
||||||
|
if (!defined('SECURITY')) die('Hacking attempt');
|
||||||
|
|
||||||
|
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
|
||||||
|
$debug->append('No cached version available, fetching from backend', 3);
|
||||||
|
if ($setting->getValue('monitoring_uptimerobot_api_keys') && $aStatus = $monitoring->getUptimeRobotStatus()) {
|
||||||
|
$smarty->assign("STATUS", $aStatus);
|
||||||
|
$smarty->assign("UPDATED", $setting->getValue('monitoring_uptimerobot_lastcheck'));
|
||||||
|
$smarty->assign("CODES", array(
|
||||||
|
0 => 'Paused',
|
||||||
|
1 => 'Unchecked',
|
||||||
|
2 => 'Up',
|
||||||
|
8 => 'Down',
|
||||||
|
9 => 'Down'
|
||||||
|
));
|
||||||
|
$smarty->assign("CONTENT", "default.tpl");
|
||||||
|
} else {
|
||||||
|
$_SESSION['POPUP'][] = array('CONTENT' => 'UptimeRobot API Key not configured.', 'TYPE' => 'info');
|
||||||
|
$smarty->assign("CONTENT", "");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$debug->append('Using cached page', 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@ -65,9 +65,12 @@ $aGlobal = array(
|
|||||||
'price' => $setting->getValue('price'),
|
'price' => $setting->getValue('price'),
|
||||||
'disable_mp' => $setting->getValue('disable_mp'),
|
'disable_mp' => $setting->getValue('disable_mp'),
|
||||||
'config' => array(
|
'config' => array(
|
||||||
|
'algorithm' => $config['algorithm'],
|
||||||
|
'target_bits' => $config['target_bits'],
|
||||||
'accounts' => $config['accounts'],
|
'accounts' => $config['accounts'],
|
||||||
'disable_invitations' => $setting->getValue('disable_invitations'),
|
'disable_invitations' => $setting->getValue('disable_invitations'),
|
||||||
'disable_notifications' => $setting->getValue('disable_notifications'),
|
'disable_notifications' => $setting->getValue('disable_notifications'),
|
||||||
|
'monitoring_uptimerobot_api_keys' => $setting->getValue('monitoring_uptimerobot_api_keys'),
|
||||||
'statistics_ajax_refresh_interval' => $statistics_ajax_refresh_interval,
|
'statistics_ajax_refresh_interval' => $statistics_ajax_refresh_interval,
|
||||||
'price' => array( 'currency' => $config['price']['currency'] ),
|
'price' => array( 'currency' => $config['price']['currency'] ),
|
||||||
'targetdiff' => $config['difficulty'],
|
'targetdiff' => $config['difficulty'],
|
||||||
@ -89,31 +92,21 @@ $aGlobal['website']['email'] = $setting->getValue('website_email');
|
|||||||
$aGlobal['website']['api']['disabled'] = $setting->getValue('disable_api');
|
$aGlobal['website']['api']['disabled'] = $setting->getValue('disable_api');
|
||||||
$aGlobal['website']['blockexplorer']['disabled'] = $setting->getValue('website_blockexplorer_disabled');
|
$aGlobal['website']['blockexplorer']['disabled'] = $setting->getValue('website_blockexplorer_disabled');
|
||||||
$aGlobal['website']['chaininfo']['disabled'] = $setting->getValue('website_chaininfo_disabled');
|
$aGlobal['website']['chaininfo']['disabled'] = $setting->getValue('website_chaininfo_disabled');
|
||||||
|
$aGlobal['website']['donors']['disabled'] = $setting->getValue('disable_donors');
|
||||||
|
$aGlobal['website']['about']['disabled'] = $setting->getValue('disable_about');
|
||||||
$setting->getValue('website_blockexplorer_url') ? $aGlobal['website']['blockexplorer']['url'] = $setting->getValue('website_blockexplorer_url') : $aGlobal['website']['blockexplorer']['url'] = 'http://explorer.litecoin.net/block/';
|
$setting->getValue('website_blockexplorer_url') ? $aGlobal['website']['blockexplorer']['url'] = $setting->getValue('website_blockexplorer_url') : $aGlobal['website']['blockexplorer']['url'] = 'http://explorer.litecoin.net/block/';
|
||||||
$setting->getValue('website_chaininfo_url') ? $aGlobal['website']['chaininfo']['url'] = $setting->getValue('website_chaininfo_url') : $aGlobal['website']['chaininfo']['url'] = 'http://allchains.info';
|
$setting->getValue('website_chaininfo_url') ? $aGlobal['website']['chaininfo']['url'] = $setting->getValue('website_chaininfo_url') : $aGlobal['website']['chaininfo']['url'] = 'http://allchains.info';
|
||||||
|
|
||||||
|
// Google Analytics
|
||||||
|
$aGlobal['statistics']['analytics']['enabled'] = $setting->getValue('statistics_analytics_enabled');
|
||||||
|
$aGlobal['statistics']['analytics']['code'] = $setting->getValue('statistics_analytics_code');
|
||||||
|
|
||||||
// ACLs
|
// ACLs
|
||||||
$aGlobal['acl']['pool']['statistics'] = $setting->getValue('acl_pool_statistics');
|
$aGlobal['acl']['pool']['statistics'] = $setting->getValue('acl_pool_statistics');
|
||||||
$aGlobal['acl']['block']['statistics'] = $setting->getValue('acl_block_statistics');
|
$aGlobal['acl']['block']['statistics'] = $setting->getValue('acl_block_statistics');
|
||||||
$aGlobal['acl']['round']['statistics'] = $setting->getValue('acl_round_statistics');
|
$aGlobal['acl']['round']['statistics'] = $setting->getValue('acl_round_statistics');
|
||||||
|
$aGlobal['acl']['blockfinder']['statistics'] = $setting->getValue('acl_blockfinder_statistics');
|
||||||
// We support some dynamic reward targets but fall back to our fixed value
|
$aGlobal['acl']['uptime']['statistics'] = $setting->getValue('acl_uptime_statistics');
|
||||||
// Special calculations for PPS Values based on reward_type setting and/or available blocks
|
|
||||||
if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
|
||||||
$pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount']));
|
|
||||||
} else {
|
|
||||||
if ($config['pps']['reward']['type'] == 'block') {
|
|
||||||
if ($aLastBlock = $block->getLast()) {
|
|
||||||
$pps_reward = $aLastBlock['amount'];
|
|
||||||
} else {
|
|
||||||
$pps_reward = $config['pps']['reward']['default'];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$pps_reward = $config['pps']['reward']['default'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$aGlobal['ppsvalue'] = number_format(round($pps_reward / (pow(2,32) * $dDifficulty) * pow(2, $config['pps_target']), 12) ,12);
|
|
||||||
|
|
||||||
// We don't want these session infos cached
|
// We don't want these session infos cached
|
||||||
if (@$_SESSION['USERDATA']['id']) {
|
if (@$_SESSION['USERDATA']['id']) {
|
||||||
@ -122,17 +115,16 @@ if (@$_SESSION['USERDATA']['id']) {
|
|||||||
|
|
||||||
// Other userdata that we can cache savely
|
// Other userdata that we can cache savely
|
||||||
$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']);
|
$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']);
|
||||||
$aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']) * $dPersonalHashrateModifier;
|
$aGlobal['userdata']['rawhashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']);
|
||||||
|
$aGlobal['userdata']['hashrate'] = $aGlobal['userdata']['rawhashrate'] * $dPersonalHashrateModifier;
|
||||||
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']);
|
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']);
|
||||||
|
|
||||||
switch ($config['payout_system']) {
|
switch ($config['payout_system']) {
|
||||||
case 'prop' || 'pplns':
|
case 'prop':
|
||||||
// Some estimations
|
// Some estimations
|
||||||
$aEstimates = $statistics->getUserEstimates($aRoundShares, $aGlobal['userdata']['shares'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees']);
|
$aEstimates = $statistics->getUserEstimates($aRoundShares, $aGlobal['userdata']['shares'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees']);
|
||||||
$aGlobal['userdata']['est_block'] = $aEstimates['block'];
|
$aGlobal['userdata']['estimates'] = $aEstimates;
|
||||||
$aGlobal['userdata']['est_fee'] = $aEstimates['fee'];
|
break;
|
||||||
$aGlobal['userdata']['est_donation'] = $aEstimates['donation'];
|
|
||||||
$aGlobal['userdata']['est_payout'] = $aEstimates['payout'];
|
|
||||||
case 'pplns':
|
case 'pplns':
|
||||||
$aGlobal['pplns']['target'] = $config['pplns']['shares']['default'];
|
$aGlobal['pplns']['target'] = $config['pplns']['shares']['default'];
|
||||||
if ($aLastBlock = $block->getLast()) {
|
if ($aLastBlock = $block->getLast()) {
|
||||||
@ -140,8 +132,31 @@ if (@$_SESSION['USERDATA']['id']) {
|
|||||||
$aGlobal['pplns']['target'] = $iAvgBlockShares;
|
$aGlobal['pplns']['target'] = $iAvgBlockShares;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$aEstimates = $statistics->getUserEstimates($aRoundShares, $aGlobal['userdata']['shares'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees']);
|
||||||
|
$aGlobal['userdata']['estimates'] = $aEstimates;
|
||||||
break;
|
break;
|
||||||
case 'pps':
|
case 'pps':
|
||||||
|
// We support some dynamic reward targets but fall back to our fixed value
|
||||||
|
// Special calculations for PPS Values based on reward_type setting and/or available blocks
|
||||||
|
if ($config['pps']['reward']['type'] == 'blockavg' && $block->getBlockCount() > 0) {
|
||||||
|
$pps_reward = round($block->getAvgBlockReward($config['pps']['blockavg']['blockcount']));
|
||||||
|
} else {
|
||||||
|
if ($config['pps']['reward']['type'] == 'block') {
|
||||||
|
if ($aLastBlock = $block->getLast()) {
|
||||||
|
$pps_reward = $aLastBlock['amount'];
|
||||||
|
} else {
|
||||||
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$pps_reward = $config['pps']['reward']['default'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$aGlobal['userdata']['pps']['unpaidshares'] = $statistics->getUserUnpaidPPSShares($_SESSION['USERDATA']['id'], $setting->getValue('pps_last_share_id'));
|
||||||
|
$aGlobal['ppsvalue'] = number_format(round($pps_reward / (pow(2, $config['target_bits']) * $dDifficulty), 12) ,12);
|
||||||
|
$aGlobal['poolppsvalue'] = $aGlobal['ppsvalue'] * pow(2, $config['difficulty'] - 16);
|
||||||
|
$aGlobal['userdata']['sharedifficulty'] = $statistics->getUserShareDifficulty($_SESSION['USERDATA']['id']);
|
||||||
|
$aGlobal['userdata']['estimates'] = $statistics->getUserEstimates($aGlobal['userdata']['sharerate'], $aGlobal['userdata']['sharedifficulty'], $aGlobal['userdata']['donate_percent'], $aGlobal['userdata']['no_fees'], $aGlobal['ppsvalue']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,5 +177,6 @@ $smarty->assign('DEBUG', DEBUG);
|
|||||||
|
|
||||||
// Make it available in Smarty
|
// Make it available in Smarty
|
||||||
$smarty->assign('PATH', 'site_assets/' . THEME);
|
$smarty->assign('PATH', 'site_assets/' . THEME);
|
||||||
|
$smarty->assign('GLOBALASSETS', 'site_assets/global');
|
||||||
$smarty->assign('GLOBAL', $aGlobal);
|
$smarty->assign('GLOBAL', $aGlobal);
|
||||||
?>
|
?>
|
||||||
|
|||||||
@ -51,7 +51,13 @@ if (is_dir(INCLUDE_DIR . '/pages/')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set a default action here if no page has been requested
|
// Set a default action here if no page has been requested
|
||||||
$page = isset($_REQUEST['page']) && isset($arrPages[$_REQUEST['page']]) ? $_REQUEST['page'] : 'home';
|
if (isset($_REQUEST['page']) && isset($arrPages[$_REQUEST['page']])) {
|
||||||
|
$page = $_REQUEST['page'];
|
||||||
|
} else if (isset($_REQUEST['page']) && ! isset($arrPages[$_REQUEST['page']])) {
|
||||||
|
$page = 'error';
|
||||||
|
} else {
|
||||||
|
$page = 'home';
|
||||||
|
}
|
||||||
|
|
||||||
// Create our pages array from existing files
|
// Create our pages array from existing files
|
||||||
if (is_dir(INCLUDE_DIR . '/pages/' . $page)) {
|
if (is_dir(INCLUDE_DIR . '/pages/' . $page)) {
|
||||||
|
|||||||
BIN
public/site_assets/global/images/flags/ad.png
Executable file
|
After Width: | Height: | Size: 643 B |
BIN
public/site_assets/global/images/flags/ae.png
Executable file
|
After Width: | Height: | Size: 408 B |
BIN
public/site_assets/global/images/flags/af.png
Executable file
|
After Width: | Height: | Size: 604 B |
BIN
public/site_assets/global/images/flags/ag.png
Executable file
|
After Width: | Height: | Size: 591 B |
BIN
public/site_assets/global/images/flags/ai.png
Executable file
|
After Width: | Height: | Size: 643 B |
BIN
public/site_assets/global/images/flags/al.png
Executable file
|
After Width: | Height: | Size: 600 B |
BIN
public/site_assets/global/images/flags/am.png
Executable file
|
After Width: | Height: | Size: 497 B |
BIN
public/site_assets/global/images/flags/an.png
Executable file
|
After Width: | Height: | Size: 488 B |
BIN
public/site_assets/global/images/flags/ao.png
Normal file
|
After Width: | Height: | Size: 428 B |
BIN
public/site_assets/global/images/flags/ar.png
Executable file
|
After Width: | Height: | Size: 506 B |
BIN
public/site_assets/global/images/flags/as.png
Executable file
|
After Width: | Height: | Size: 647 B |
BIN
public/site_assets/global/images/flags/at.png
Executable file
|
After Width: | Height: | Size: 403 B |
BIN
public/site_assets/global/images/flags/au.png
Executable file
|
After Width: | Height: | Size: 673 B |
BIN
public/site_assets/global/images/flags/aw.png
Executable file
|
After Width: | Height: | Size: 524 B |
BIN
public/site_assets/global/images/flags/ax.png
Executable file
|
After Width: | Height: | Size: 663 B |
BIN
public/site_assets/global/images/flags/az.png
Executable file
|
After Width: | Height: | Size: 589 B |
BIN
public/site_assets/global/images/flags/ba.png
Executable file
|
After Width: | Height: | Size: 593 B |
BIN
public/site_assets/global/images/flags/bb.png
Executable file
|
After Width: | Height: | Size: 585 B |
BIN
public/site_assets/global/images/flags/bd.png
Executable file
|
After Width: | Height: | Size: 504 B |
BIN
public/site_assets/global/images/flags/be.png
Executable file
|
After Width: | Height: | Size: 449 B |
BIN
public/site_assets/global/images/flags/bf.png
Executable file
|
After Width: | Height: | Size: 497 B |
BIN
public/site_assets/global/images/flags/bg.png
Executable file
|
After Width: | Height: | Size: 462 B |
BIN
public/site_assets/global/images/flags/bh.png
Executable file
|
After Width: | Height: | Size: 457 B |
BIN
public/site_assets/global/images/flags/bi.png
Executable file
|
After Width: | Height: | Size: 675 B |
BIN
public/site_assets/global/images/flags/bj.png
Executable file
|
After Width: | Height: | Size: 486 B |
BIN
public/site_assets/global/images/flags/bm.png
Executable file
|
After Width: | Height: | Size: 611 B |
BIN
public/site_assets/global/images/flags/bn.png
Executable file
|
After Width: | Height: | Size: 639 B |
BIN
public/site_assets/global/images/flags/bo.png
Executable file
|
After Width: | Height: | Size: 500 B |
BIN
public/site_assets/global/images/flags/br.png
Executable file
|
After Width: | Height: | Size: 593 B |
BIN
public/site_assets/global/images/flags/bs.png
Executable file
|
After Width: | Height: | Size: 526 B |
BIN
public/site_assets/global/images/flags/bt.png
Executable file
|
After Width: | Height: | Size: 631 B |
BIN
public/site_assets/global/images/flags/bv.png
Executable file
|
After Width: | Height: | Size: 512 B |
BIN
public/site_assets/global/images/flags/bw.png
Executable file
|
After Width: | Height: | Size: 443 B |