From 6257c3639269bd4955fc47c773be0cedbf41cb7b Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 1 Oct 2015 18:28:16 -0700 Subject: [PATCH] Multithreaded input scanning. --- src/kernel.cpp | 133 ++++++++++++++++++++++++++++++++++++++++------------ src/kernel.h | 2 +- src/rpcmining.cpp | 20 ++++++-- 3 files changed, 117 insertions(+), 38 deletions(-) diff --git a/src/kernel.cpp b/src/kernel.cpp index 9c63eaf..b95f4db 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -438,51 +438,122 @@ void GetKernelMidstate(uint64_t nStakeModifier, uint32_t nBlockTime, uint32_t nT SHA256_Update(&ctx, (unsigned char*)&it[0], 8 + 16); } + +class ScanMidstateWorker +{ +public: + ScanMidstateWorker() + { } + ScanMidstateWorker(SHA256_CTX ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval) + { + workerSolutions = vector >(); + + workerCtx = ctx; + this->nBits = nBits; + this->nInputTxTime = nInputTxTime; + this->nValueIn = nValueIn; + this->SearchInterval = SearchInterval; + } + + void Do() + { + CBigNum bnTargetPerCoinDay; + bnTargetPerCoinDay.SetCompact(nBits); + + // Get maximum possible target to filter out the majority of obviously insufficient hashes + CBigNum bnMaxTargetPerCoinDay = bnTargetPerCoinDay * CBigNum(nValueIn) * nStakeMaxAge / COIN / (24 * 60 * 60); + uint256 maxTarget = bnMaxTargetPerCoinDay.getuint256(); + + SHA256_CTX ctx = workerCtx; + + // Search forward in time from the given timestamp + // Stopping search in case of shutting down + for (uint32_t nTimeTx=SearchInterval.first; nTimeTx maxTarget) + continue; + + CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); + CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; + + if (bnTargetProofOfStake >= CBigNum(hashProofOfStake)) + { + workerSolutions.push_back(std::pair(hashProofOfStake, nTimeTx)); + } + } + } + + vector > GetSolutions() + { + return workerSolutions; + } + +private: + SHA256_CTX workerCtx; + std::vector > workerSolutions; + + uint32_t nBits; + uint32_t nInputTxTime; + int64_t nValueIn; + std::pair SearchInterval; +}; + // Scan given midstate for solution -bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::pair &solution) +bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::vector > &solutions) { - CBigNum bnTargetPerCoinDay; - bnTargetPerCoinDay.SetCompact(nBits); + // TODO: custom threads amount - // Get maximum possible target to filter out the majority of obviously insufficient hashes - CBigNum bnMaxTargetPerCoinDay = bnTargetPerCoinDay * CBigNum(nValueIn) * nStakeMaxAge / COIN / (24 * 60 * 60); - uint256 maxTarget = bnMaxTargetPerCoinDay.getuint256(); + uint32_t nBegin = SearchInterval.first; + uint32_t nEnd = SearchInterval.second; + uint32_t nPart = (nEnd - nBegin) / 4; - SHA256_CTX ctxCopy = ctx; + ScanMidstateWorker workers[4]; - // Search forward in time from the given timestamp - // Stopping search in case of shutting down - for (uint32_t nTimeTx=SearchInterval.first; nTimeTx interval(nBegin, nIntervalEnd); + workers[i] = ScanMidstateWorker(ctx, nBits, nInputTxTime, nValueIn, interval); - // Skip if hash doesn't satisfy the maximum target - if (hashProofOfStake > maxTarget) - continue; + boost::function workerFnc = boost::bind(&ScanMidstateWorker::Do, &workers[i]); + group.create_thread(workerFnc); + } - CBigNum bnCoinDayWeight = CBigNum(nValueIn) * GetWeight((int64_t)nInputTxTime, (int64_t)nTimeTx) / COIN / (24 * 60 * 60); - CBigNum bnTargetProofOfStake = bnCoinDayWeight * bnTargetPerCoinDay; + group.join_all(); + solutions.clear(); - if (bnTargetProofOfStake >= CBigNum(hashProofOfStake)) - { - solution.first = hashProofOfStake; - solution.second = nTimeTx; + for(int i = 0; i<4; i++) + { + std::vector > ws = workers[i].GetSolutions(); + solutions.insert(solutions.end(), ws.begin(), ws.end()); + } - return true; - } + if (solutions.size() == 0) + { + // no solutions + return false; } - return false; + return true; } // Scan given midstate for solution diff --git a/src/kernel.h b/src/kernel.h index eca9744..e4b1a43 100644 --- a/src/kernel.h +++ b/src/kernel.h @@ -37,7 +37,7 @@ bool CheckStakeKernelHash(unsigned int nBits, const CBlock& blockFrom, uint32_t void GetKernelMidstate(uint64_t nStakeModifier, uint32_t nBlockTime, uint32_t nTxOffset, uint32_t nInputTxTime, uint32_t nOut, SHA256_CTX &ctx); // Scan given midstate for kernel solutions -bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::pair &solution); +bool ScanMidstateForward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::vector > &solutions); bool ScanMidstateBackward(SHA256_CTX &ctx, uint32_t nBits, uint32_t nInputTxTime, int64_t nValueIn, std::pair &SearchInterval, std::pair &solution); // Check kernel hash target and coinstake signature diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 6937e84..01cfa7f 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -135,14 +135,22 @@ Value scaninput(const Array& params, bool fHelp) SHA256_CTX ctx; GetKernelMidstate(nStakeModifier, block.nTime, txindex.pos.nTxPos - txindex.pos.nBlockPos, tx.nTime, nOut, ctx); - std::pair solution; - if (ScanMidstateForward(ctx, nBits, tx.nTime, tx.vout[nOut].nValue, interval, solution)) + std::vector > solutions; + if (ScanMidstateForward(ctx, nBits, tx.nTime, tx.vout[nOut].nValue, interval, solutions)) { - Object r; - r.push_back(Pair("hash", solution.first.GetHex())); - r.push_back(Pair("time", DateTimeStrFormat(solution.second))); + Array sols; - return r; + BOOST_FOREACH(const PAIRTYPE(uint256, uint32_t) solution, solutions) + { + + Object r; + r.push_back(Pair("hash", solution.first.GetHex())); + r.push_back(Pair("time", DateTimeStrFormat(solution.second))); + + sols.push_back(r); + } + + return sols; } } else -- 1.7.1