diff --git a/src/miner.cpp b/src/miner.cpp index 5c91541c5..aeb4d9215 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -1049,6 +1049,18 @@ class RandomXSolverCanceledException : public std::exception } }; +class RamhashSolverCanceledException : public std::exception +{ + virtual const char* what() const throw() { + return "Ramhash solver was canceled"; + } +}; + +enum RamhashSolverCancelCheck +{ + Reason1 +}; + enum RandomXSolverCancelCheck { Reason1, @@ -1610,8 +1622,116 @@ void static RamhashMiner() // Use the current block as input ramhashInput << pblocktemplate->block; //TODO: calculate actual ramhash hash with input - //TODO: Use hash to build a valid block - } + // ramHash = ... + // Use hash to build a valid block + std::function)> validBlock = +#ifdef ENABLE_WALLET + [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] +#else + [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams] +#endif + (std::vector soln) { + int32_t z; arith_uint256 h; CBlock B; + // Write the solution to the hash and compute the result. + rhdebug("%s: Checking solution against target\n"); + pblock->nSolution = soln; + solutionTargetChecks.increment(); + // fprintf(stderr,"%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get()); + B = *pblock; + h = UintToArith256(B.GetHash()); + + rhdebug("%s: h="); + if (fRamhashDebug) { + for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&h)[z]); + fprintf(stderr," , hashTarget="); + for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]); + fprintf(stderr,"\n"); + } + + if ( h > hashTarget ) + { + rhdebug("%s: h > hashTarget"); + return false; + } + + CValidationState state; + if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false)) + { + h = UintToArith256(B.GetHash()); + fprintf(stderr,"RamhashMiner: Invalid ramhash block mined, try again "); + for (z=31; z>=0; z--) + fprintf(stderr,"%02x",((uint8_t *)&h)[z]); + gotinvalid = 1; + fprintf(stderr,"\n"); + return(false); + } + SetThreadPriority(THREAD_PRIORITY_NORMAL); + LogPrintf("HushRamhashMiner:\n"); + LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", B.GetHash().GetHex(), HASHTarget.GetHex()); +#ifdef ENABLE_WALLET + if (ProcessBlockFound(&B, *pwallet, reservekey)) { +#else + if (ProcessBlockFound(&B)) { +#endif + // Ignore chain updates caused by us + std::lock_guard lock{m_cs}; + cancelSolver = false; + } + SetThreadPriority(THREAD_PRIORITY_LOWEST); + // In regression test mode, stop mining after a block is found. + if (chainparams.MineBlocksOnDemand()) { + // Increment here because throwing skips the call below + // TODO: equivalent of ehSolverRuns.increment(); + throw boost::thread_interrupted(); + } + return true; + }; + std::function cancelled = [&m_cs, &cancelSolver](RamhashSolverCancelCheck pos) { + std::lock_guard lock{m_cs}; + return cancelSolver; + }; + + try { + // Use the ramhash hash as the block solution + std::vector sol_char(ramhashHash, ramhashHash+32); + bool found = validBlock(sol_char); + if (found) { + rhdebug("%s: found solution!\n"); + // If we find a POW solution, do not try other solutions + // because they become invalid as we created a new block in blockchain. + break; + } else { + rhdebug("%s: solution not found, validBlock=false\n"); + } + } catch (RamhashSolverCanceledException&) { + LogPrintf("HushRamhashMiner solver canceled\n"); + std::lock_guard lock{m_cs}; + cancelSolver = false; + } + + boost::this_thread::interruption_point(); + + if (vNodes.empty() && chainparams.MiningRequiresPeers()) + { + if ( Mining_height > ASSETCHAINS_MINHEIGHT ) + { + fprintf(stderr,"%s: no nodes, break\n", __func__); + break; + } + } + if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff) + { + fprintf(stderr,"%s: nonce & 0xffff == 0xffff, break\n", __func__); + break; + } + // Update nNonce and nTime + pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1); + pblock->nBits = savebits; + } + + } // while(true) } } catch (const boost::thread_interrupted&) { miningTimer.stop();