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}