diff --git a/cronjobs/findblock.php b/cronjobs/findblock.php index 28dddb4b..5c168448 100755 --- a/cronjobs/findblock.php +++ b/cronjobs/findblock.php @@ -72,7 +72,8 @@ if (empty($aAllBlocks)) { foreach ($aAllBlocks as $iIndex => $aBlock) { if (empty($aBlock['share_id'])) { // Fetch this blocks upstream ID - if ($share->setUpstream($block->getLastUpstreamId(), $aBlock['time'])) { + $aBlockInfo = $bitcoin->query('getblock', $aBlock['blockhash']); + if ($share->setUpstream($aBlockInfo, $block->getLastUpstreamId())) { $iCurrentUpstreamId = $share->getUpstreamId(); $iAccountId = $user->getUserId($share->getUpstreamFinder()); } else { diff --git a/public/include/classes/share.class.php b/public/include/classes/share.class.php index 5e4db85e..ca5b1478 100644 --- a/public/include/classes/share.class.php +++ b/public/include/classes/share.class.php @@ -177,7 +177,41 @@ class Share { * @param last int Skips all shares up to last to find new share * @return bool **/ - public function setUpstream($last=0, $time=0) { + public function setUpstream($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'])); + $merkleroot = pack("H*", swapEndian($aBlock['merkleroot']) ); + $time = pack("I*", $aBlock['time']); + $bits = pack("H*", swapEndian($aBlock['bits'])); + $nonce = pack("I*", $aBlock['nonce']); + $header_bin = $version . $previousblockhash . $merkleroot . $time . $bits . $nonce; + $header_hex = implode(unpack("H*", $header_bin)); + $scrypt_hash = swapEndian(bin2hex(Scrypt::calc($header_bin, $header_bin, 1024, 1, 1, 32))); + + + // 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']); + echo "ppheader : $ppheader \n"; + echo "header : $header_hex \n"; + echo "Scrypt hash : $scrypt_hash \n"; + + $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id FROM $this->table WHERE solution = ? LIMIT 1"); + if ($this->checkStmt($stmt) && $stmt->bind_param('s', $scrypt_hash) && $stmt->execute() && $result = $stmt->get_result()->num_rows > 0) { + $this->oUpstream = $result->fetch_object(); + if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id)) + return true; + } + + // Failed to fetch via startum solution, try pushpoold + $stmt = $this->mysqli->prepare("SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, 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()) { + $this->oUpstream = $result->fetch_object(); + if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id)) + return true; + } + + // Still no match, try upstream result with timerange $stmt = $this->mysqli->prepare(" SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id @@ -185,13 +219,15 @@ class Share { WHERE upstream_result = 'Y' AND id > ? AND UNIX_TIMESTAMP(time) >= ? + AND UNIX_TIMESTAMP(time) <= ? + 60 ORDER BY id ASC LIMIT 1"); - if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $time) && $stmt->execute() && $result = $stmt->get_result()) { + if ($this->checkStmt($stmt) && $stmt->bind_param('iii', $last, $aBlock['time'], $Block['time']) && $stmt->execute() && $result = $stmt->get_result()) { $this->oUpstream = $result->fetch_object(); if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id)) return true; } - // First attempt failed, we do a fallback with any share available for now + + // We failed again, now we take ANY result matching the timestamp $stmt = $this->mysqli->prepare(" SELECT SUBSTRING_INDEX( `username` , '.', 1 ) AS account, id @@ -200,7 +236,7 @@ class Share { AND id > ? AND UNIX_TIMESTAMP(time) >= ? ORDER BY id ASC LIMIT 1"); - if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $last, $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(); if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id)) return true; diff --git a/public/include/lib/scrypt.php b/public/include/lib/scrypt.php index 87ddff2e..3d501b7d 100644 --- a/public/include/lib/scrypt.php +++ b/public/include/lib/scrypt.php @@ -523,4 +523,14 @@ $value = Scrypt::calc($i, $i, 1024, 1, 1, 32); */ +// Function used for pushpoold solution checks +function word_reverse($str) { + $ret = ''; + while (strlen($str) > 0) { + $ret .= substr($str, -8, 8); + $str = substr($str, 0, -8); + } + return $ret; +} + ?>