Merge branch 'next' into issue-145

This commit is contained in:
Sebastian Grewe 2013-09-06 10:55:31 +02:00
commit f87a7fc380
16 changed files with 362 additions and 14 deletions

View File

@ -111,3 +111,9 @@ Small Time Miners are running various stratum only pools for different coins.
| http://ftc.nut2pools.com | Feathercoin | 45-50Mhs | 25 workers | New style, PPLNS |
| http://wdc.nut2pools.com | Worldcoin | 3.5 Mhs | 3 workers | New style, PPLNS |
| http://pxc.nut2pools.com | Phenixcoin | 0 | 0 | New style | PPLNS |
### Dids
| Pool URL | Coin | Avg. Hashrate | Avg. Active Workers | Notes |
| -------- | ---- | ------------: | ------------------: | ----- |
| http://poolmine.it | Litecoin | 0.23 MHash | 5 | PPLNS, Custom Template |

View File

@ -41,6 +41,7 @@ require_once(CLASS_DIR . '/invitation.class.php');
require_once(CLASS_DIR . '/share.class.php');
require_once(CLASS_DIR . '/worker.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 . '/notification.class.php');
require_once(CLASS_DIR . '/news.class.php');

View File

@ -133,9 +133,8 @@ class Block {
* @param confirmations int Required confirmations to consider block confirmed
* @return data array Array with database fields as keys
**/
public function getAllUnconfirmed() {
public function getAllUnconfirmed($confirmations=120) {
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE confirmations < ? AND confirmations > -1");
empty($this->config['network_confirmations']) ? $confirmations = 120 : $confirmations = $this->config['network_confirmations'];
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $confirmations) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
return false;

View File

@ -164,9 +164,13 @@ class Notification extends Mail {
if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) {
if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData)) {
return true;
} else {
$this->setErrorMessage('SendMail call failed: ' . $this->mail->getError());
return false;
}
} else {
$this->setErrorMessage('User disabled ' . $strType . ' notifications');
return false;
}
$this->setErrorMessage('Error sending mail notification');
return false;
@ -178,5 +182,5 @@ $notification->setDebug($debug);
$notification->setMysql($mysqli);
$notification->setSmarty($smarty);
$notification->setConfig($config);
$notification->setSetting($setting);
?>

View File

@ -0,0 +1,160 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
class RoundStats {
private $sError = '';
private $tableTrans = 'transactions';
private $tableStats = 'statistics_shares';
private $tableBlocks = 'blocks';
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
**/
public function getNextBlock($iHeight=0) {
$stmt = $this->mysqli->prepare("
SELECT height
FROM $this->tableBlocks
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 false;
}
/**
* Get prev block for round stats
**/
public function getPreviousBlock($iHeight=0) {
$stmt = $this->mysqli->prepare("
SELECT height
FROM $this->tableBlocks
WHERE height < ?
ORDER BY height DESC
LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_object()->height;
return false;
}
/**
* Get details for block height
* @param height int Block Height
* @return data array Block information from DB
**/
public function getDetailsForBlockHeight($iHeight=0, $isAdmin=0) {
$stmt = $this->mysqli->prepare("
SELECT
b.id, height, amount, confirmations, difficulty, FROM_UNIXTIME(time) as time, shares,
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS finder
FROM $this->tableBlocks as b
LEFT JOIN $this->tableUsers AS a ON b.account_id = a.id
WHERE b.height = ? LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_assoc();
return false;
}
/**
* Get shares statistics for round block height
* @param height int Block Height
* @return data array Block information from DB
**/
public function getRoundStatsForAccounts($iHeight=0, $isAdmin=0) {
$stmt = $this->mysqli->prepare("
SELECT
IF(a.is_anonymous, IF( ? , a.username, 'anonymous'), a.username) AS username,
s.valid,
s.invalid
FROM $this->tableStats AS s
LEFT JOIN $this->tableBlocks AS b ON s.block_id = b.id
LEFT JOIN $this->tableUsers AS a ON a.id = s.account_id
WHERE b.height = ?
GROUP BY username ASC
ORDER BY valid DESC
");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $isAdmin, $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
return false;
}
/**
* Get all transactions for round block height for admin
* @param height int Block Height
* @return data array Block round transactions
**/
public function getAllRoundTransactions($iHeight=0) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT
t.id AS id,
a.username AS username,
t.type AS type,
t.amount AS amount
FROM $this->tableTrans AS t
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
WHERE b.height = ?
ORDER BY id ASC");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $iHeight) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
$this->debug->append('Unable to fetch transactions');
return false;
}
/**
* Get transactions for round block height user id
* @param height int Block Height
* @param id int user id
* @return data array Block round transactions for user id
**/
public function getUserRoundTransactions($iHeight=0, $id=0) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT
t.id AS id,
a.username AS username,
t.type AS type,
t.amount AS amount
FROM $this->tableTrans AS t
LEFT JOIN $this->tableBlocks AS b ON t.block_id = b.id
LEFT JOIN $this->tableUsers AS a ON t.account_id = a.id
WHERE b.height = ? AND a.id = ?
ORDER BY id ASC");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $iHeight, $id) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
$this->debug->append('Unable to fetch transactions');
return false;
}
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;
}
}
$roundstats = new RoundStats($debug, $mysqli, $config);

View File

@ -108,12 +108,19 @@ $aSettings['acl'][] = array(
'tooltip' => 'Make the pool statistics page private (users only) or public.'
);
$aSettings['acl'][] = array(
'display' => 'Blcok Statistics', 'type' => 'select',
'display' => 'Block Statistics', 'type' => 'select',
'options' => array( 0 => 'Private', 1 => 'Public'),
'default' => 1,
'name' => 'acl_block_statistics', 'value' => $setting->getValue('acl_block_statistics'),
'tooltip' => 'Make the block statistics page private (users only) or public.'
);
$aSettings['acl'][] = array(
'display' => 'Round Statistics', 'type' => 'select',
'options' => array( 0 => 'Private', 1 => 'Public'),
'default' => 1,
'name' => 'acl_round_statistics', 'value' => $setting->getValue('acl_round_statistics'),
'tooltip' => 'Make the round statistics page private (users only) or public.'
);
$aSettings['system'][] = array(
'display' => 'Disable e-mail confirmations', 'type' => 'select',
'options' => array( 0 => 'No', 1 => 'Yes' ),

View File

@ -11,6 +11,9 @@ define('CLASS_DIR', INCLUDE_DIR . '/classes');
// Our pages directory which takes care of
define('PAGES_DIR', INCLUDE_DIR . '/pages');
// Our theme folder holding all themes
define('THEME_DIR', BASEPATH . 'templates');
// Set debugging level for our debug class
define('DEBUG', 0);

View File

@ -0,0 +1,45 @@
<?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 (@$_REQUEST['next'] && !empty($_REQUEST['height'])) {
$iKey = $roundstats->getNextBlock($_REQUEST['height']);
} 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'];
}
}
echo $iKey;
$aDetailsForBlockHeight = $roundstats->getDetailsForBlockHeight($iKey, $user->isAdmin($_SESSION['USERDATA']['id']));
$aRoundShareStats = $roundstats->getRoundStatsForAccounts($iKey, $user->isAdmin($_SESSION['USERDATA']['id']));
if ($user->isAdmin($_SESSION['USERDATA']['id'])) {
$aUserRoundTransactions = $roundstats->getAllRoundTransactions($iKey);
} else {
$aUserRoundTransactions = $roundstats->getUserRoundTransactions($iKey, $_SESSION['USERDATA']['id']);
}
// Propagate content our template
$smarty->assign('BLOCKDETAILS', $aDetailsForBlockHeight);
$smarty->assign('ROUNDSHARES', $aRoundShareStats);
$smarty->assign("ROUNDTRANSACTIONS", $aUserRoundTransactions);
} else {
$debug->append('Using cached page', 3);
}
if ($setting->getValue('acl_round_statistics')) {
$smarty->assign("CONTENT", "default.tpl");
} else if ($user->isAuthenticated()) {
$smarty->assign("CONTENT", "default.tpl");
}
?>

View File

@ -74,6 +74,7 @@ $setting->getValue('website_chaininfo_url') ? $aGlobal['website']['chaininfo']['
// ACLs
$aGlobal['acl']['pool']['statistics'] = $setting->getValue('acl_pool_statistics');
$aGlobal['acl']['block']['statistics'] = $setting->getValue('acl_block_statistics');
$aGlobal['acl']['round']['statistics'] = $setting->getValue('acl_round_statistics');
// 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

View File

@ -30,6 +30,7 @@
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=pool">Pool Stats</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=blocks">Block Stats</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=graphs">Hashrate Graphs</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=round">Round Stats</a></li>
</ul>
</li>
{else}
@ -40,6 +41,9 @@
{/if}
{if $GLOBAL.acl.block.statistics}
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=blocks">Block Stats</a></li>
{/if}
{if $GLOBAL.acl.round.statistics}
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=round">Round Stats</a></li>
{/if}
</ul>
{/if}

View File

@ -55,11 +55,7 @@ target and network difficulty and assuming a zero variance scenario.
{assign var="totalshares" value=$totalshares+$BLOCKSFOUND[block].shares}
{assign var="count" value=$count+1}
<tr class="{cycle values="odd,even"}">
{if ! $GLOBAL.website.blockexplorer.disabled}
<td class="center"><a href="{$GLOBAL.website.blockexplorer.url}{$BLOCKSFOUND[block].blockhash}" target="_blank">{$BLOCKSFOUND[block].height}</a></td>
{else}
<td class="center">{$BLOCKSFOUND[block].height}</td>
{/if}
<td class="center"><a href="{$smarty.server.PHP_SELF}?page=statistics&action=round&height={$BLOCKSFOUND[block].height}">{$BLOCKSFOUND[block].height}</a></td>
<td class="center">
{if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}
<font color="green">Confirmed</font>

View File

@ -13,11 +13,7 @@
{assign var=rank value=1}
{section block $BLOCKSFOUND}
<tr class="{cycle values="odd,even"}">
{if ! $GLOBAL.website.blockexplorer.disabled}
<td class="center"><a href="{$GLOBAL.website.blockexplorer.url}{$BLOCKSFOUND[block].blockhash}" target="_new">{$BLOCKSFOUND[block].height}</a></td>
{else}
<td class="center">{$BLOCKSFOUND[block].height}</td>
{/if}
<td><a href="{$smarty.server.PHP_SELF}?page=statistics&action=round&height={$BLOCKSFOUND[block].height}">{$BLOCKSFOUND[block].height}</a></td>
<td>{if $BLOCKSFOUND[block].is_anonymous|default:"0" == 1}anonymous{else}{$BLOCKSFOUND[block].finder|default:"unknown"|escape}{/if}</td>
<td class="center">{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}</td>
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>

View File

@ -0,0 +1,65 @@
{include file="global/block_header.tpl" ALIGN="left" BLOCK_STYLE="width: 100%" BLOCK_HEADER="Block Stats" STYLE="padding-left:5px;padding-right:5px;"}
<table align="left" width="100%" border="0" style="font-size:13px;"><tbody><tr><td class="left">
<table align="left" width="100%" border="0" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th align="left">Name</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ID</td>
<td>{$BLOCKDETAILS.id|default:"0"}</td>
</tr>
<tr class="even">
<td>Height</td>
{if ! $GLOBAL.website.blockexplorer.disabled}
<td><a href="{$GLOBAL.website.blockexplorer.url}{$BLOCKDETAILS.blockhash}" target="_new">{$BLOCKDETAILS.height}</a></td>
{else}
<td>{$BLOCKDETAILS.height}</td>
{/if}
</tr>
<tr class="odd">
<td>Amount</td>
<td>{$BLOCKDETAILS.amount|default:"0"}</td>
</tr>
<tr class="even">
<td>Confirmations</td>
<td>{$BLOCKDETAILS.confirmations|default:"0"}</td>
</tr>
<tr class="odd">
<td>Difficulty</td>
<td>{$BLOCKDETAILS.difficulty|default:"0"}</td>
</tr>
<tr class="even">
<td>Time</td>
<td>{$BLOCKDETAILS.time|default:"0"}</td>
</tr>
<tr class="odd">
<td>Shares</td>
<td>{$BLOCKDETAILS.shares|default:"0"}</td>
</tr>
<tr class="even">
<td>Finder</td>
<td>{$BLOCKDETAILS.finder|default:"0"}</td>
</tr>
</tbody>
</table></td>
<td class="right">
<form action="{$smarty.server.PHP_SELF}" method="POST" id='height'>
<input type="hidden" name="page" value="{$smarty.request.page}">
<input type="hidden" name="action" value="{$smarty.request.action}">
<input type="text" class="pin" name="height" value="{$smarty.request.height|default:"%"}">
<input type="submit" class="submit small" value="Search">
</form></td></tr>
<tr>
<td class="left">
<a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page}&action={$smarty.request.action}&height={$BLOCKDETAILS.height}&prev=1"><img src="{$PATH}/images/prev.png" /></a>
</td>
<td class="right">
<a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page}&action={$smarty.request.action}&height={$BLOCKDETAILS.height}&next=1"><img src="{$PATH}/images/next.png" /></a>
</td>
</tr>
</tbody></table>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,9 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Round Statistics" BLOCK_STYLE="clear:none;"}
{include file="statistics/round/block_stats.tpl"}
{include file="statistics/round/round_transactions.tpl"}
{include file="statistics/round/round_shares.tpl"}
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,28 @@
{include file="global/block_header.tpl" ALIGN="left" BLOCK_HEADER="Round Shares" }
<center>
<table width="100%" border="0" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th class="center">Rank</th>
<th class="left" scope="col">User Name</th>
<th class="right" scope="col">Valid</th>
<th class="right" scope="col">Invalid</th>
<th class="right" scope="col">Invalid %</th>
</tr>
</thead>
<tbody>
{assign var=rank value=1}
{assign var=listed value=0}
{section contrib $ROUNDSHARES}
<tr{if $GLOBAL.userdata.username == $ROUNDSHARES[contrib].username}{assign var=listed value=1} style="background-color:#99EB99;"{else} class="{cycle values="odd,even"}"{/if}>
<td class="center">{$rank++}</td>
<td>{if $ROUNDSHARES[contrib].is_anonymous|default:"0" == 1}anonymous{else}{$ROUNDSHARES[contrib].username|escape}{/if}</td>
<td class="right">{$ROUNDSHARES[contrib].valid|number_format}</td>
<td class="right">{$ROUNDSHARES[contrib].invalid|number_format}</td>
<td class="right">{($ROUNDSHARES[contrib].invalid / $ROUNDSHARES[contrib].valid * 100)|number_format:"2"}</td>
</tr>
{/section}
</tbody>
</table>
</center>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,24 @@
{include file="global/block_header.tpl" ALIGN="right" BLOCK_HEADER="Round Transactions"}
<center>
<table width="100%" border="0" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th align="left">Tx Id</th>
<th scope="col">User Name</th>
<th scope="col">Type</th>
<th class="right" scope="col">Amount</th>
</tr>
</thead>
<tbody>
{section txs $ROUNDTRANSACTIONS}
<tr class="{cycle values="odd,even"}">
<td>{$ROUNDTRANSACTIONS[txs].id|default:"0"}</td>
<td>{$ROUNDTRANSACTIONS[txs].username|escape}</td>
<td class="right">{$ROUNDTRANSACTIONS[txs].type|default:""}</td>
<td class="right">{$ROUNDTRANSACTIONS[txs].amount|default:"0"|number_format:"8"}</td>
</tr>
{/section}
</tbody>
</table>
</center>
{include file="global/block_footer.tpl"}