commit
a841880fe7
@ -51,17 +51,17 @@ if (empty($aTransactions['transactions'])) {
|
||||
// Let us add those blocks as unaccounted
|
||||
foreach ($aTransactions['transactions'] as $iIndex => $aData) {
|
||||
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'];
|
||||
$aData['height'] = $aBlockInfo['height'];
|
||||
$aData['difficulty'] = $aBlockInfo['difficulty'];
|
||||
$aData['height'] = $aBlockRPCInfo['height'];
|
||||
$aData['difficulty'] = $aBlockRPCInfo['difficulty'];
|
||||
$log->logInfo(substr($aData['blockhash'], 0, 15) . "...\t" .
|
||||
$aData['height'] . "\t" .
|
||||
$aData['amount'] . "\t" .
|
||||
$aData['confirmations'] . "\t\t" .
|
||||
$aData['difficulty'] . "\t" .
|
||||
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!");
|
||||
continue;
|
||||
}
|
||||
@ -78,38 +78,65 @@ if (empty($aAllBlocks)) {
|
||||
$log->logDebug('No new blocks without share_id found in database');
|
||||
} else {
|
||||
// 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\t\tType");
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
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
|
||||
if (!$iPreviousShareId = $block->getLastShareId()) {
|
||||
$iPreviousShareId = $block->getLastShareId();
|
||||
if ( !$iPreviousShareId && $block->getBlockCount() > 1) {
|
||||
$iPreviousShareId = 0;
|
||||
$log->logInfo('Unable to find highest share ID found so far, if this is your first block, this is normal.');
|
||||
// $log->logError('Unable to find highest share ID found so far, assuming share ID 0 as previous found upstream share.');
|
||||
}
|
||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
|
||||
|
||||
// Store new information
|
||||
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
|
||||
$log->logError('Failed to update share ID in database for block ' . $aBlock['height']);
|
||||
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
||||
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height']);
|
||||
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
||||
$log->logError('Failed to update share count in database for block ' . $aBlock['height']);
|
||||
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']);
|
||||
// Fetch this blocks upstream ID
|
||||
$aBlockRPCInfo = $bitcoin->query('getblock', $aBlock['blockhash']);
|
||||
if ($share->findUpstreamShare($aBlockRPCInfo, $iPreviousShareId)) {
|
||||
$iCurrentUpstreamId = $share->getUpstreamShareId();
|
||||
// Out of order share detection
|
||||
if ($iCurrentUpstreamId < $iPreviousShareId) {
|
||||
// Fetch our offending block
|
||||
$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->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "E0002: Upstream shares not found");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
// 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!');
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "E0003: Failed share update");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
// 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->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "E0004: Failed to reset block");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(1);
|
||||
}
|
||||
$monitoring->setStatus($cron_name . "_active", "yesno", 0);
|
||||
$monitoring->setStatus($cron_name . "_message", "message", "Out of Order Share detected, autofixed");
|
||||
$monitoring->setStatus($cron_name . "_status", "okerror", 1);
|
||||
exit(0);
|
||||
} else {
|
||||
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
|
||||
$iAccountId = $user->getUserId($share->getUpstreamFinder());
|
||||
}
|
||||
} else {
|
||||
$log->logFatal('E0005: 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(1);
|
||||
}
|
||||
|
||||
$log->logInfo(
|
||||
@ -122,6 +149,17 @@ if (empty($aAllBlocks)) {
|
||||
. $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']);
|
||||
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
||||
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height']);
|
||||
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
||||
$log->logError('Failed to update share count in database for block ' . $aBlock['height']);
|
||||
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']);
|
||||
}
|
||||
|
||||
if ($setting->getValue('disable_notifications') != 1) {
|
||||
// Notify users
|
||||
$aAccounts = $notification->getNotificationAccountIdByType('new_block');
|
||||
|
||||
@ -8,8 +8,12 @@ if (!defined('SECURITY'))
|
||||
// some cross-class functions.
|
||||
class Base {
|
||||
private $sError = '';
|
||||
protected $table = '';
|
||||
private $values = array(), $types = '';
|
||||
|
||||
public function getTableName() {
|
||||
return $this->table;
|
||||
}
|
||||
public function setDebug($debug) {
|
||||
$this->debug = $debug;
|
||||
}
|
||||
@ -50,6 +54,13 @@ class Base {
|
||||
return $this->sError;
|
||||
}
|
||||
|
||||
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
|
||||
* @param value string Value to search for
|
||||
|
||||
@ -56,6 +56,30 @@ class Block {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get our last, highest share ID inserted for a block
|
||||
* @param none
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
class Share {
|
||||
private $sError = '';
|
||||
private $table = 'shares';
|
||||
class Share Extends Base {
|
||||
protected $table = 'shares';
|
||||
private $tableArchive = 'shares_archive';
|
||||
private $oUpstream;
|
||||
private $iLastUpstreamId;
|
||||
@ -22,14 +21,6 @@ class Share {
|
||||
$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
|
||||
* @param none
|
||||
@ -38,13 +29,43 @@ class Share {
|
||||
public function getArchiveTableName() {
|
||||
return $this->tableArchive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch normal table name for this class
|
||||
* @param none
|
||||
* @return data string Table name
|
||||
* Fetch a single share by ID
|
||||
* @param id int Share ID
|
||||
* @return array Share data
|
||||
**/
|
||||
public function getTableName() {
|
||||
return $this->table;
|
||||
public function getShareById($id) {
|
||||
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 false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +250,7 @@ class Share {
|
||||
public function getUpstreamFinder() {
|
||||
return @$this->oUpstream->account;
|
||||
}
|
||||
public function getUpstreamId() {
|
||||
public function getUpstreamShareId() {
|
||||
return @$this->oUpstream->id;
|
||||
}
|
||||
/**
|
||||
@ -240,7 +261,7 @@ class Share {
|
||||
* @param last int Skips all shares up to last to find new share
|
||||
* @return bool
|
||||
**/
|
||||
public function setUpstream($aBlock, $last=0) {
|
||||
public function findUpstreamShare($aBlock, $last=0) {
|
||||
// Many use stratum, so we create our stratum check first
|
||||
$version = pack("I*", sprintf('%08d', $aBlock['version']));
|
||||
$previousblockhash = pack("H*", swapEndian($aBlock['previousblockhash']));
|
||||
@ -358,18 +379,10 @@ class Share {
|
||||
return $result->fetch_object()->share_id;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->setMysql($mysqli);
|
||||
$share->setConfig($config);
|
||||
$share->setUser($user);
|
||||
$share->setBlock($block);
|
||||
|
||||
@ -5,7 +5,8 @@ if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
class Transaction extends Base {
|
||||
private $sError = '', $table = 'transactions';
|
||||
private $sError = '';
|
||||
protected $table = 'transactions';
|
||||
public $num_rows = 0, $insert_id = 0;
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user