diff --git a/.gitignore b/.gitignore index 67b09557..24c42d14 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,17 @@ +# Local Config /public/include/config/global.inc.php + +# Templates /public/templates/compile/*.php +/public/templates/cache/*.php + +# Logs /cronjobs/logs/*.txt /cronjobs/logs/*.txt.*.gz -/public/templates/cache/*.php + # Test configs public/include/config/global.inc.scrypt.php public/include/config/global.inc.sha.php + +# IDE Settings +/.idea/* diff --git a/cronjobs/run-maintenance.sh b/cronjobs/run-maintenance.sh new file mode 100644 index 00000000..3c76eb26 --- /dev/null +++ b/cronjobs/run-maintenance.sh @@ -0,0 +1,126 @@ +#!/bin/bash + + +######################### +# # +# Configuration Options # +# # +######################### +# PHP Detections, if this fails hard code it +PHP_BIN=$( which php ) + +# List of cruns to execute +CRONS="tickerupdate.php notifications.php statistics.php archive_cleanup.php" + +# Output additional runtime information +VERBOSE="1" + +# Base path for PIDFILE, (full path). +BASEPATH="/tmp" + +# Subfolder for PIDFILE, so it's path will be unique in a multipool server. +# Path relative to BASEPATH. +# Eg. SUBFOLDER="LTC" +SUBFOLDER="" + +################################################################ +# # +# You probably don't need to change anything beyond this point # +# # +################################################################ + +# 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 +ME=$( basename $0 ) + +# Overwrite some settings via command line arguments +while getopts "hfvp:d:" opt; do + case "$opt" in + h|\?) + echo "Usage: $0 [-v] [-p PHP_BINARY] [-d SUBFOLDER]"; + exit 0 + ;; + v) VERBOSE=1 ;; + f) PHP_OPTS="$PHP_OPTS -f";; + p) PHP_BIN=$OPTARG ;; + d) SUBFOLDER=$OPTARG ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# Path to PID file, needs to be writable by user running this +PIDFILE="${BASEPATH}/${SUBFOLDER}/${ME}.pid" +# Clean PIDFILE path +PIDFILE=$($READLINK -m "$PIDFILE") + +# Create folders recursively if necessary +if ! $(mkdir -p $( dirname $PIDFILE)); then + echo "Error creating PIDFILE path: $( dirname $PIDFILE )" + exit 1 +fi + +# Find scripts path +if [[ -L $0 ]]; then + CRONHOME=$( dirname $( $READLINK $0 ) ) +else + CRONHOME=$( dirname $0 ) +fi + +# Change working director to CRONHOME +if ! cd $CRONHOME 2>/dev/null; then + echo "Unable to change to working directory \$CRONHOME: $CRONHOME" + exit 1 +fi + +# Confiuration checks +if [[ -z $PHP_BIN || ! -x $PHP_BIN ]]; then + echo "Unable to locate you php binary." + exit 1 +fi + +if [[ ! -e 'shared.inc.php' ]]; then + echo "Not in cronjobs folder, please ensure \$CRONHOME is set!" + exit 1 +fi + +# Our PID of this shell +PID=$$ + +if [[ -e $PIDFILE ]]; then + echo "Cron seems to be running already" + RUNPID=$( cat $PIDFILE ) + if ps fax | grep -q "^\<$RUNPID\>"; then + echo "Process found in process table, aborting" + exit 1 + else + echo "Process $RUNPID not found. Plese remove $PIDFILE if process is indeed dead." + exit 1 + fi +fi + +# Write our PID file +echo $PID > $PIDFILE + +for cron in $CRONS; do + [[ $VERBOSE == 1 ]] && echo "Running $cron, check logfile for details" + $PHP_BIN $cron $PHP_OPTS +done + +# Remove pidfile +rm -f $PIDFILE diff --git a/cronjobs/run-payout.sh b/cronjobs/run-payout.sh new file mode 100644 index 00000000..4d65010d --- /dev/null +++ b/cronjobs/run-payout.sh @@ -0,0 +1,126 @@ +#!/bin/bash + + +######################### +# # +# Configuration Options # +# # +######################### +# PHP Detections, if this fails hard code it +PHP_BIN=$( which php ) + +# List of cruns to execute +CRONS="findblock.php proportional_payout.php pplns_payout.php pps_payout.php blockupdate.php payouts.php" + +# Output additional runtime information +VERBOSE="1" + +# Base path for PIDFILE, (full path). +BASEPATH="/tmp" + +# Subfolder for PIDFILE, so it's path will be unique in a multipool server. +# Path relative to BASEPATH. +# Eg. SUBFOLDER="LTC" +SUBFOLDER="" + +################################################################ +# # +# You probably don't need to change anything beyond this point # +# # +################################################################ + +# 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 +ME=$( basename $0 ) + +# Overwrite some settings via command line arguments +while getopts "hfvp:d:" opt; do + case "$opt" in + h|\?) + echo "Usage: $0 [-v] [-p PHP_BINARY] [-d SUBFOLDER]"; + exit 0 + ;; + v) VERBOSE=1 ;; + f) PHP_OPTS="$PHP_OPTS -f";; + p) PHP_BIN=$OPTARG ;; + d) SUBFOLDER=$OPTARG ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +# Path to PID file, needs to be writable by user running this +PIDFILE="${BASEPATH}/${SUBFOLDER}/${ME}.pid" +# Clean PIDFILE path +PIDFILE=$($READLINK -m "$PIDFILE") + +# Create folders recursively if necessary +if ! $(mkdir -p $( dirname $PIDFILE)); then + echo "Error creating PIDFILE path: $( dirname $PIDFILE )" + exit 1 +fi + +# Find scripts path +if [[ -L $0 ]]; then + CRONHOME=$( dirname $( $READLINK $0 ) ) +else + CRONHOME=$( dirname $0 ) +fi + +# Change working director to CRONHOME +if ! cd $CRONHOME 2>/dev/null; then + echo "Unable to change to working directory \$CRONHOME: $CRONHOME" + exit 1 +fi + +# Confiuration checks +if [[ -z $PHP_BIN || ! -x $PHP_BIN ]]; then + echo "Unable to locate you php binary." + exit 1 +fi + +if [[ ! -e 'shared.inc.php' ]]; then + echo "Not in cronjobs folder, please ensure \$CRONHOME is set!" + exit 1 +fi + +# Our PID of this shell +PID=$$ + +if [[ -e $PIDFILE ]]; then + echo "Cron seems to be running already" + RUNPID=$( cat $PIDFILE ) + if ps fax | grep -q "^\<$RUNPID\>"; then + echo "Process found in process table, aborting" + exit 1 + else + echo "Process $RUNPID not found. Plese remove $PIDFILE if process is indeed dead." + exit 1 + fi +fi + +# Write our PID file +echo $PID > $PIDFILE + +for cron in $CRONS; do + [[ $VERBOSE == 1 ]] && echo "Running $cron, check logfile for details" + $PHP_BIN $cron $PHP_OPTS +done + +# Remove pidfile +rm -f $PIDFILE diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php index fc24e7f9..01982c2a 100644 --- a/public/include/classes/statistics.class.php +++ b/public/include/classes/statistics.class.php @@ -800,6 +800,41 @@ class Statistics extends Base { public function getEstimatedShares($dDiff) { return round((POW(2, (32 - $this->config['target_bits'])) * $dDiff) / pow(2, ($this->config['difficulty'] - 16))); } + + /** + * Get the Expected Time per Block in the whole Network in seconde + * @return seconds double Seconds per Block + */ + public function getNetworkExpectedTimePerBlock(){ + if ($data = $this->memcache->get(__FUNCTION__)) return $data; + + if ($this->bitcoin->can_connect() === true) { + $dNetworkHashrate = $this->bitcoin->getnetworkhashps(); + $dDifficulty = $this->bitcoin->getdifficulty(); + } else { + $dNetworkHashrate = 0; + $dDifficulty = 1; + } + + return pow(2, 32) * $dDifficulty / $dNetworkHashrate; + } + + /** + * Get the Expected next Difficulty + * @return difficulty double Next difficulty + */ + public function getExpectedNextDifficulty(){ + if ($data = $this->memcache->get(__FUNCTION__)) return $data; + + if ($this->bitcoin->can_connect() === true) { + $dDifficulty = $this->bitcoin->getdifficulty(); + } else { + $dDifficulty = 1; + } + + return round($dDifficulty * $this->config['cointarget'] / $this->getNetworkExpectedTimePerBlock(), 8); + } + } $statistics = new Statistics(); @@ -810,6 +845,7 @@ $statistics->setUser($user); $statistics->setBlock($block); $statistics->setMemcache($memcache); $statistics->setConfig($config); +$statistics->setBitcoin($bitcoin); $statistics->setErrorCodes($aErrorCodes); ?> diff --git a/public/include/pages/api/getdashboarddata.inc.php b/public/include/pages/api/getdashboarddata.inc.php index efc9d743..5be24aee 100644 --- a/public/include/pages/api/getdashboarddata.inc.php +++ b/public/include/pages/api/getdashboarddata.inc.php @@ -104,9 +104,12 @@ if ($iEstShares > 0 && $aRoundShares['valid'] > 0) { $dEstPercent = 0; } +$dExpectedTimePerBlock = $statistics->getNetworkExpectedTimePerBlock(); +$dEstNextDifficulty = $statistics->getExpectedNextDifficulty(); + // Output JSON format $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, 'esttimeperblock' => $dExpectedTimePerBlock, 'nextdifficulty' => $dEstNextDifficulty ) ), 'personal' => array ( 'hashrate' => $dPersonalHashrateAdjusted, 'sharerate' => $dPersonalSharerate, 'sharedifficulty' => $dPersonalShareDifficulty, 'shares' => array('valid' => $aUserRoundShares['valid'], 'invalid' => $aUserRoundShares['invalid'], 'invalid_percent' => $dUserInvalidPercent, 'unpaid' => $dUnpaidShares ), @@ -123,7 +126,7 @@ $data = array( '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, 'esttimeperblock' => round($dExpectedTimePerBlock ,2), 'nextdifficulty' => $dEstNextDifficulty ), ); echo $api->get_json($data); diff --git a/public/include/pages/dashboard.inc.php b/public/include/pages/dashboard.inc.php index 06b4f3b3..86ccc331 100644 --- a/public/include/pages/dashboard.inc.php +++ b/public/include/pages/dashboard.inc.php @@ -35,11 +35,14 @@ if ($user->isAuthenticated()) { // Avoid confusion, ensure our nethash isn't higher than poolhash if ($iCurrentPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $iCurrentPoolHashrate; + $dExpectedTimePerBlock = $statistics->getNetworkExpectedTimePerBlock(); + $dEstNextDifficulty = $statistics->getExpectedNextDifficulty(); + // 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('NETWORK', array('difficulty' => $dDifficulty, 'block' => $iBlock, 'EstNextDifficulty' => $dEstNextDifficulty, 'EstTimePerBlock' => $dExpectedTimePerBlock)); $smarty->assign('INTERVAL', $interval / 60); $smarty->assign('CONTENT', 'default.tpl'); } diff --git a/public/include/pages/statistics/pool.inc.php b/public/include/pages/statistics/pool.inc.php index e1af1af5..1e3f65f3 100644 --- a/public/include/pages/statistics/pool.inc.php +++ b/public/include/pages/statistics/pool.inc.php @@ -8,10 +8,12 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { // Fetch data from wallet if ($bitcoin->can_connect() === true){ $dDifficulty = $bitcoin->getdifficulty(); + $dNetworkHashrate = $bitcoin->getnetworkhashps(); $iBlock = $bitcoin->getblockcount(); is_int($iBlock) && $iBlock > 0 ? $sBlockHash = $bitcoin->query('getblockhash', $iBlock) : $sBlockHash = ''; } else { $dDifficulty = 1; + $dNetworkHashrate = 1; $iBlock = 0; $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to wallet RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); } @@ -50,6 +52,9 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { $dEstPercent = 0; } + $dExpectedTimePerBlock = $statistics->getNetworkExpectedTimePerBlock(); + $dEstNextDifficulty = $statistics->getExpectedNextDifficulty(); + // Propagate content our template $smarty->assign("ESTTIME", $iEstTime); $smarty->assign("TIMESINCELAST", $dTimeSinceLast); @@ -59,7 +64,7 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { $smarty->assign("CONTRIBHASHES", $aContributorsHashes); $smarty->assign("CURRENTBLOCK", $iBlock); $smarty->assign("CURRENTBLOCKHASH", @$sBlockHash); - $smarty->assign('NETWORK', array('difficulty' => $dDifficulty, 'block' => $iBlock)); + $smarty->assign('NETWORK', array('difficulty' => $dDifficulty, 'block' => $iBlock, 'EstNextDifficulty' => $dEstNextDifficulty, 'EstTimePerBlock' => $dExpectedTimePerBlock)); $smarty->assign('ESTIMATES', array('shares' => $iEstShares, 'percent' => $dEstPercent)); if (count($aBlockData) > 0) { $smarty->assign("LASTBLOCK", $aBlockData['height']); diff --git a/public/templates/mobile/statistics/pool/general_stats.tpl b/public/templates/mobile/statistics/pool/general_stats.tpl index 2f25a4a4..b0ef0e17 100644 --- a/public/templates/mobile/statistics/pool/general_stats.tpl +++ b/public/templates/mobile/statistics/pool/general_stats.tpl @@ -30,11 +30,19 @@ {if ! $GLOBAL.website.chaininfo.disabled} Current Difficulty - {$DIFFICULTY} + {$DIFFICULTY} + + + Est. Next Difficulty + {$NETWORK.EstNextDifficulty} {/if} - Est. Avg. Time per Round + Est. Avg. Time per Round (Network) + {$NETWORK.ExpectedTimePerBlock|seconds_to_words} + + + Est. Avg. Time per Round (Pool) {$ESTTIME|seconds_to_words} diff --git a/public/templates/mpos/account/edit/default.tpl b/public/templates/mpos/account/edit/default.tpl index ccb324a8..920a36f1 100644 --- a/public/templates/mpos/account/edit/default.tpl +++ b/public/templates/mpos/account/edit/default.tpl @@ -35,7 +35,7 @@
{$GLOBAL.config.ap_threshold.min}-{$GLOBAL.config.ap_threshold.max} {$GLOBAL.config.currency}. Set to '0' for no auto payout. - +
diff --git a/public/templates/mpos/admin/settings/default.tpl b/public/templates/mpos/admin/settings/default.tpl index a4c4d5c0..7ab60aed 100644 --- a/public/templates/mpos/admin/settings/default.tpl +++ b/public/templates/mpos/admin/settings/default.tpl @@ -21,7 +21,7 @@ {if $SETTINGS.$TAB[setting].type == 'select'} {html_options name="data[{$SETTINGS.$TAB[setting].name}]" options=$SETTINGS.$TAB[setting].options selected=$SETTINGS.$TAB[setting].value|default:$SETTINGS.$TAB[setting].default} {else if $SETTINGS.$TAB[setting].type == 'text'} - + {else if $SETTINGS.$TAB[setting].type == 'textarea'} {else} diff --git a/public/templates/mpos/dashboard/js_api.tpl b/public/templates/mpos/dashboard/js_api.tpl index 4a402675..f04bd9b5 100644 --- a/public/templates/mpos/dashboard/js_api.tpl +++ b/public/templates/mpos/dashboard/js_api.tpl @@ -140,6 +140,8 @@ $(document).ready(function(){ $('#b-pvalid').html(data.getdashboarddata.data.pool.shares.valid); $('#b-pivalid').html(data.getdashboarddata.data.pool.shares.invalid + " (" + data.getdashboarddata.data.pool.shares.invalid_percent + "%)" ); $('#b-diff').html(data.getdashboarddata.data.network.difficulty); + $('#b-nextdiff').html(data.getdashboarddata.data.network.nextdifficulty); + $('#b-esttimeperblock').html(data.getdashboarddata.data.network.esttimeperblock + " seconds"); // <- this needs some nicer format $('#b-nblock').html(data.getdashboarddata.data.network.block); $('#b-target').html(data.getdashboarddata.data.pool.shares.estimated + " (done: " + data.getdashboarddata.data.pool.shares.progress + "%)" ); {/literal}{if $GLOBAL.config.payout_system != 'pps'}{literal } diff --git a/public/templates/mpos/dashboard/network_info.tpl b/public/templates/mpos/dashboard/network_info.tpl index 1c8691c5..c470794b 100644 --- a/public/templates/mpos/dashboard/network_info.tpl +++ b/public/templates/mpos/dashboard/network_info.tpl @@ -5,6 +5,14 @@ Difficulty {$NETWORK.difficulty} + + Est Next Difficulty + {$NETWORK.EstNextDifficulty} + + + Est. Avg. Time per Block + {$NETWORK.EstTimePerBlock|seconds_to_words} + Current Block {$NETWORK.block} diff --git a/public/templates/mpos/statistics/pool/general_stats.tpl b/public/templates/mpos/statistics/pool/general_stats.tpl index 7b34ed84..100d8b84 100644 --- a/public/templates/mpos/statistics/pool/general_stats.tpl +++ b/public/templates/mpos/statistics/pool/general_stats.tpl @@ -24,7 +24,19 @@ {/if} - Est. Avg. Time per Round + Est. Next Difficulty + {if ! $GLOBAL.website.chaininfo.disabled} + {$NETWORK.EstNextDifficulty} + {else} + {$NETWORK.EstNextDifficulty} + {/if} + + + Est. Avg. Time per Round (Network) + {$NETWORK.EstTimePerBlock|seconds_to_words} + + + Est. Avg. Time per Round (Pool) {$ESTTIME|seconds_to_words} diff --git a/sql/000_base_structure.sql b/sql/000_base_structure.sql index adeb6e7e..6c8acc1a 100644 --- a/sql/000_base_structure.sql +++ b/sql/000_base_structure.sql @@ -215,7 +215,7 @@ CREATE TABLE IF NOT EXISTS `transactions` ( KEY `archived` (`archived`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -CREATE TABLE `templates` ( +CREATE TABLE IF NOT EXISTS `templates` ( `template` varchar(255) NOT NULL, `active` tinyint(1) NOT NULL DEFAULT 0, `content` mediumtext,